!20071 merge 15383 into master

dfx sdd

Created-by: wendel
Commit-by: wendel
Merged-by: openharmony_ci
Description: **IssueNo**:

**Description**:

**稳定性自检:**
| 自检项                                                       | 自检结果  |
| ------------------------------------------------------------ | -------- |
| 涉及跨进程调用的相关操作需要抛至主线程或加锁防止并发              |          |
| 成员变量进行赋值或创建需要排查并发                               |          |
| 谨慎在lambda表达式中使用引用捕获                                |          |
| 谨慎在未经拷贝的情况下使用外部传入的string、C字符串               |          |
| map\vector\list\set等stl模板类使用时需要排查并发                |          |
| 谨慎考虑加锁范围                                               |          |
| 在IPC通信中谨慎使用同步通信方式                                 |          |
| 禁止传递this指针至其他模块或线程(特别是eventhandler任务)        |          |
| 禁止将外部传入的裸指针在内部直接构造智能指针                      |          |
| 禁止多个独立创建的智能指针管理同一地址                           |          |
| 禁止在析构函数中抛异步任务                                      |          |
| 禁止js对象在非js线程(例如在IPC线程)创建、使用或销毁             |          |
| 禁止在对外接口中未经判空直接使用外部传入的指针                    |          |
| 禁止接口返回局部变量引用                                        |          |
| 禁止在信号函数中加锁                                            |          |
| 禁止在关键流程(SA启动、应用启动等主流程)执行耗时的操作           |          |
| 禁止将同一个cpp编译在不同的so中                                 |          |

**安全编码自检:**
| 自检项                                                          | 自检结果 |
| -------------------------------------------------------------- | -------- |
| 裸指针避免通过隐式转换构造为sptr                                 |          |
| json对象在取值之前必须先判断类型,避免类型不匹配                   |          |
| 序列化时必须对传入的数组大小进行校验,避免出现超大数组              |          |
| 避免使用未明确位宽的整型,选择使用int8_t、uint8_t等类型            |          |
| 外部传入的路径要做规范化校验,对路径中的.、..、../等特殊字符严格校验 |          |
| 指针变量、表示资源描述符的变量、bool变量必须赋初值                  |          |
| readParcelable获取的对象使用前需要判空                            |          |
| 分配和释放内存的函数需要成对出现                                   |          |
| 申请内存后异常退出前需要及时进行内存释放                            |          |
| 内存申请前必须对内存大小进行合法性校验                              |          |
| 内存分配后必须判断是否成功                                         |          |
| 禁止使用realloc、alloca函数                                       |          |
| 禁止打印文件路径、口令等敏感信息,如有需要,使用private修饰          |          |
| 禁止打印内存地址                                                  |          |
| 整数之间运算时必须严格检查,确保不会出现溢出、反转、除0               |          |
| 禁止对有符号整数进行位操作符运算                                    |          |
| 禁止对指针进行逻辑或位运算                                         |          |
| 循环次数如果收外部数据控制,需要检验其合法性                         |          |
| 禁止使用内存操作类危险函数,需要使用安全函数                         |          |
| 谨慎使用不可重入函数                                               |          |
| 必须检查安全函数的返回值,并进行正确处理                             |          |
| 禁止仅通过TokenType类型判断绕过权限校验                             |          |

**TDD Result**:

**XTS Result**:

### 是否已执行L0用例
- [ ] 已验证
- [ ] 不涉及。如不涉及,请写明理由

### AI检视评分(使用本地代码检视skills扫描):



See merge request: openharmony/ability_ability_runtime!20071
This commit is contained in:
openharmony_ci
2026-08-05 17:50:57 +08:00
4 changed files with 1548 additions and 0 deletions
@@ -0,0 +1,343 @@
# 架构设计
> 本设计承接 `proposal.md`(条件通过)与 `spec.md`Draft),固化 `execTool` 的架构约束、关键设计决策与模块影响。设计 AC ⊆ spec AC,不发明新行为。
## 设计元数据
| 字段 | 内容 |
|------|-----|
| Design ID | DESIGN-CLI-001 |
| 关联需求 | `proposal.md`REQ-010 |
| 关联 Epic | 无(独立特性) |
| 目标 Feature | FEAT-CLI-001 |
| 复杂度 | 标准 |
| 目标版本 | OpenHarmony-6.0-Release(待确认) |
| Owner | 待确认 |
| 状态 | Draft |
## 需求基线
> 需求基线详见 proposal.md。以下仅列出设计阶段需额外强调的要点。
| 项 | 补充说明 |
|----|----------|
| 仅系统应用 + EXEC_CLI_TOOL | 安全边界由 SA 186 入口统一执行,不在 NAPI 层做权限判定 |
| HAP 沙箱前置 | 沙箱配置由调用方 Token 生成,非 HAP 直接拒绝(35700003 |
| 会话内存态不持久化 | 不涉及 RDB/Preferences,无跨版本数据兼容约束 |
## 上下文和现状
### 涉及仓和模块
| 仓库 | 补充架构说明 |
|------|-------------|
| foundation/ability/ability_runtime | 服务层(services/)与 SDK 层(interfaces/kits/)解耦;cli_tool_framework 自成子系统,经 IDL 生成 IPC Stub/Proxy;服务侧依赖 `services/common` 的权限/日志/事件上报设施 |
### 调用链层级分析
| 层 | 模块 | 职责 | 修改类型 |
|----|------|------|----------|
| NAPI | `frameworks/js/napi/cli_tool_manager` | JS↔C++ 绑定:参数解析、同步校验、Promise/异步回调派发 | 修改(既有实现,固化契约) |
| InnerAPI/IPC | `interfaces/cli_tool`IDL 生成) | `ICliToolManager` Proxy/Stub、`ICliToolManagerScheduler` 回复回调、Parcelable 数据结构 | 修改(既有实现,固化契约) |
| 服务 | `services/climgr` | SA 186 服务端:权限校验、工具查找、参数/schema 校验、沙箱生成、子进程、会话/超时/让出、IO 监控、事件派发 | 修改(既有实现,固化契约) |
| 服务/公共 | `services/common``cli_tool_framework/services/common` | 权限工具、HiSysEvent 上报、HiLog 标签 | 不变(复用) |
| SA 注册 | `services/sa_profile/186.json` | SA 186 注册到 samgr(进程 aimgr,库 libclimgr.z.soondemand | 不变 |
**检查项:**
- [x] 调用链每一层都已覆盖(NAPI→InnerAPI/IPC→服务→SA 注册)
- [x] 每层职责边界清晰,无跨层违规(NAPI 不直接调 services 内部;服务不反向依赖 NAPI)
- [x] 每层修改类型明确
### 适用架构规则
| Rule ID | 适用原因 | 设计结论 | 验证方式 |
|---------|----------|----------|----------|
| OH-ARCH-LAYERING | NAPI→InnerAPI/IPC→服务 三层调用 | 调用方向自上而下;服务不反向依赖 NAPI;框架层不直接引用 services 内部头文件 | 依赖检查/代码评审 |
| OH-ARCH-SUBSYSTEM | 单子系统 ability 内闭环 | 不跨子系统调用 | 代码评审 |
| OH-ARCH-IPC-SAF | 跨进程经 SA 186 | oneway `ExecTool` + `SchedulerExecToolReplyEvent` 回复;客户端按需拉起 SA | 集成测试 |
| OH-ARCH-API-LEVEL | 新增 System API | System 级、需 `ohos.permission.EXEC_CLI_TOOL`、系统应用限定 | API 评审/XTS |
| OH-ARCH-COMPONENT-BUILD | 复用既有 component/parts | 无新增 componentBUILD.gn 无新增源文件(既有实现固化) | 构建验证 |
| OH-ARCH-ERROR-LOG | 错误码/HiSysEvent | 错误码 357000xx 区间;失败路径上报 bundleName/toolName/failureReason | 单测/hilog/hisysevent |
## 不涉及项承接
| 维度 | 设计结论 |
|------|----------|
| 安全与权限 | 入口在 SA 做「系统应用 + EXEC_CLI_TOOL」双校验;沙箱由调用方 Token 生成,非 HAP 拒绝;失败经 HiSysEvent 上报。详见「安全基础检查」 |
| API/SDK | 新增 System API `execTool`;签名/d.ts/权限见「API 签名、Kit 与权限」 |
| IPC/跨进程 | oneway IPC + Scheduler 回复;客户端 Scheduler Stub 接收回复并派发到 NAPI 异步任务。详见「时序设计」「线程与并发模型」 |
## 关键设计决策
| 决策 ID | 问题 | 推荐方案 | 探索过的替代方案 | 取舍理由 | 影响 |
|---------|------|----------|-----------------|------|------|
| ADR-1 | 执行承载位置 | SA 186(aimgr)集中承载 | 备选1:应用进程内 fork+exec(放弃,绕过权限/沙箱/审计);备选2:独立 SA(放弃,复用 aimgr 进程更内聚) | CLI 执行涉及权限/沙箱/超时/审计,集中到 SA 统一安全边界与并发控制 | 服务端实现集中在 climgr |
| ADR-2 | 调用回复模型 | oneway `ExecTool` + `SchedulerExecToolReplyEvent` 异步回复 | 备选1:同步 IPC 返回(放弃,子进程执行可能超 timeout,同步阻塞 Binder);备选2:客户端轮询 QuerySession(放弃,延迟与功耗差) | 子进程执行时长不定(最长 1800s),同步 IPC 不可行;oneway+回调让回复时机由服务端决定 | IPC 接口为 oneway;客户端须建 Scheduler Stub |
| ADR-3 | 前台长任务返回时机 | yieldMs 让出:定时器到点切后台并派发 reply | 备选1:进程退出才返回(放弃,长任务让调用方长时间无响应);备选2:长轮询(放弃,功耗高) | yield 让调用方在 yieldMs 处拿到 running 会话后可订阅事件,兼顾响应性与长任务 | 引入 yieldMs 参数与 yield 定时器 |
| ADR-4 | 超时实现 | ffrt 延时任务(`PostExecToolTask` | 备选1:独立 watchdog 线程(放弃,ffrt 已提供延时能力更轻量);备选2:alarm 信号(放弃,精度与可组合性差) | 复用 ffrt 延时任务,与既有调度一致 | 超时/让出各一个延时任务 |
| ADR-5 | 并发控制 | 全局会话表 + 系统配置上限 | 备选1:按调用方限流(放弃,全局资源更需保护);备选2:无上限(放弃,易资源耗尽) | CLI 子进程消耗系统资源,需全局上限保护 | `ValidateSessionLimit` 在入口校验 |
## 设计骨架
### 骨架范围
| 骨架项 | 目标 | 不包含 | 验证方式 |
|--------|------|--------|----------|
| API/接口骨架 | `execTool` 签名、ExecOptions/CliSessionInfo/ExecResult 数据模型 | 完整业务逻辑 | 编译 + API 快照 |
| 模块骨架 | NAPI 入口、IDL 接口、climgr 服务类 | 复杂策略调优 | 构建通过 |
| 测试骨架 | exec_tool_param/exec_options/cli_session_info/process_manager 测试 fixture | 全场景 | 最小用例通过 |
### 骨架 Spec 拆分
| Task ID | 目标 | 受影响文件 | AC |
|---------|------|------------|-----|
| TASK-SKELETON-1 | 建立接口/数据结构骨架 | `interfaces/cli_tool/` | WHEN 编译 THEN IDL/Parcelable 生成通过 |
## 后续 Task 拆分
| Task ID | 目标 | 受影响文件 | 依赖 |
|---------|------|------------|------|
| TASK-CLI-001 | 正常执行链路(权限→查找→校验→沙箱→子进程→会话→回复) | `services/climgr/src/cli_tool_manager_service.cpp` 等 | design + spec Approved |
| TASK-CLI-002 | 会话语义(前台/让出/后台)reply 时机 | `cli_tool_manager_service.cpp``session_record.cpp` | TASK-CLI-001 |
| TASK-CLI-003 | 超时/让出定时器与终态派发 | `cli_tool_manager_service.cpp``process_manager.cpp` | TASK-CLI-002 |
| TASK-CLI-004 | 权限/非 HAP/SA 不可用异常路径 | `cli_tool_manager_service.cpp``cli_tool_mgr_client.cpp` | TASK-CLI-001 |
| TASK-CLI-005 | 参数/schema/超时边界校验 | `tool_util.cpp``exec_options.cpp` | TASK-CLI-001 |
| TASK-CLI-006 | NAPI 参数同步校验 | `js_cli_manager.cpp` | TASK-CLI-001 |
| TASK-CLI-007 | 会话上限与并发保护 | `cli_tool_manager_service.cpp` | TASK-CLI-001 |
| TASK-CLI-008 | DFX/HiSysEvent 失败上报 | `cli_event_report` | TASK-CLI-004 |
## API 签名、Kit 与权限
### 新增 API
| API 签名 | 类型 | Kit | d.ts 位置 | 权限要求 | SysCap |
|----------|------|-----|-----------|----------|--------|
| `execTool(toolName: string, subcommand: string, args: object, challenge: string, options?: ExecOptions): Promise<CliSessionInfo>` | System | CliToolKit | `cli_tool_framework/interfaces/.../*.d.ts`(待确认) | `ohos.permission.EXEC_CLI_TOOL` + 系统应用 | 待确认 |
### 变更/废弃 API
无。
## 构建系统影响
### BUILD.gn 变更
```
文件路径: cli_tool_framework/interfaces/cli_tool/BUILD.gn
变更说明: 无新增源文件;IDL 接口与 cli_tool_client 库既有,固化契约不改构建。
```
```
文件路径: cli_tool_framework/services/climgr/BUILD.gn
变更说明: 无新增源文件;climgr SA 库既有,固化契约不改构建。
```
```
文件路径: cli_tool_framework/frameworks/js/napi/cli_tool_manager/BUILD.gn
变更说明: 无新增源文件;NAPI 模块既有,固化契约不改构建。
```
### bundle.json 变更
无新增 component;复用既有 `ability_runtime` part。若 `ohos.permission.EXEC_CLI_TOOL` 尚未在权限定义仓声明,需在该仓补登记(不在本仓)。
---
## 可选设计扩展
### 架构图
```
[系统应用/NAPI execTool] → [cli_tool_client Proxy] →(IPC oneway)→ [SA 186 climgr ExecTool]
↑ SchedulerExecToolReplyEvent 回复 ↓
└── [NapiAsyncTask Resolve/Reject] ← [cli_tool_mgr_scheduler_recipient] [ProcessManager 创建沙箱子进程]
[IOMonitor 监控 stdout/stderr/stdin]
[EventDispatcher 派发 IO/Exit/Error 事件]
```
### 数据流/控制流
| 步骤 | 调用方 | 被调用方 | 数据/接口 | 说明 |
|------|--------|----------|-----------|------|
| 1 | NAPI | cli_tool_client | `ExecTool(param, callback)` | 解析参数建 ExecToolParam |
| 2 | cli_tool_client | SA 186 | `ICliToolManager::ExecTool`oneway | 拉起 SA(按需)并 IPC |
| 3 | SA 186 | PermissionUtil | VerifyAccessToken | 系统应用 + EXEC_CLI_TOOL |
| 4 | SA 186 | CliToolDataManager | GetToolByName | 工具查找 |
| 5 | SA 186 | ToolUtil | ValidateProperties/GenerateSandboxConfig | schema 校验 + 沙箱 |
| 6 | SA 186 | ProcessManager | CreateChildProcess | fork 沙箱子进程 |
| 7 | SA 186 | IOMonitor | RegisterSession | 监控管道 + 调度 yield/timeout 定时器 |
| 8 | SA 186 | EventDispatcher | DispatchExecToolReplyEvent | 经 Scheduler 回复 |
| 9 | cli_tool_client | NapiAsyncTask | Resolve/Reject | 派发到 JS Promise |
### 时序设计
```mermaid
sequenceDiagram
participant App as 系统应用(NAPI)
participant Client as cli_tool_client
participant SA as SA 186 climgr
participant Proc as 子进程
App->>Client: execTool(param)
Client->>SA: ExecTool(param,eventId,scheduler) [oneway]
SA->>SA: 权限+查找+校验+沙箱
SA->>Proc: CreateChildProcess(fork)
SA->>SA: RegisterSessionWithMonitors(yield/timeout 定时器)
alt background=true
SA-->>Client: SchedulerExecToolReplyEvent(running)
else foreground yieldMs>0
SA-->>Client: SchedulerExecToolReplyEvent(running) @yieldMs
else foreground no-yield
Proc-->>SA: 退出+输出排空
SA-->>Client: SchedulerExecToolReplyEvent(completed/failed)
end
Client-->>App: Promise resolve(CliSessionInfo)
```
### 算法与状态机
```mermaid
stateDiagram-v2
[*] --> SPAWNING: CreateChildProcess
SPAWNING --> RUNNING: 子进程创建成功+会话登记
RUNNING --> CANCELLING: timeout/kill/clear
RUNNING --> COMPLETED: 进程退出+输出排空
RUNNING --> FAILED: 非零退出/异常
CANCELLING --> COMPLETED: 清理完成
CANCELLING --> FAILED: 清理完成
COMPLETED --> [*]
FAILED --> [*]
```
> CliSessionInfo.status 字符串映射:RUNNING→"running"、COMPLETED→"completed"、FAILED→"failed"。
### 测试性设计
| 测试层级 | 测试目标 | Mock 策略 | 验证方式 |
|----------|----------|-----------|----------|
| 单元测试 | Parcelable 编解码、参数/schema 校验、超时边界 | Mock 服务端 | `exec_tool_param_test`/`exec_options_test`/`tool_util_test` |
| 单元测试 | 客户端错误码与回复派发 | Mock `ICliToolManager`/`Scheduler` | `cli_tool_mgr_client_test`/`cli_tool_mgr_scheduler_recipient_test` |
| 集成测试 | 正常执行链路、会话语义、超时/让出 | 真实 SA + 测试工具 | `process_manager_test`/`cli_tool_mgr_service_test` |
| 集成测试 | 子进程创建与管道 | 真实 fork | `process_manager_test` |
### 异常传播时序图
```mermaid
sequenceDiagram
participant App as 应用层
participant FW as cli_tool_client
participant SA as SA 186
App->>FW: execTool(param)
FW->>SA: ExecTool [oneway]
alt 权限/非系统/非HAP/上限/工具不存在/参数非法
SA-->>FW: SchedulerExecToolReplyEvent(错误码)
FW-->>App: Promise reject(错误码)
else SA 不可用
FW-->>App: Promise reject(35700000)
else 超时
SA->>SA: HandleProcessTimeout(kill)
SA-->>FW: SchedulerExecToolReplyEvent(timeout)
SA-->>App: DispatchErrorEvent("session timed out")
end
```
| 异常场景 | 触发层 | 传播路径 | 最终处理 |
|----------|--------|----------|----------|
| 非系统应用/缺权限 | SA 入口 | SA→Scheduler→NAPI | reject 35700008/35700007 |
| 非 HAP | SA 沙箱生成 | SA→Scheduler→NAPI | reject 35700003 |
| 工具/子命令不存在 | SA 查找 | SA→Scheduler→NAPI | reject 35700005 |
| schema/参数非法 | SA 校验 | SA→Scheduler→NAPI | reject 35700002 |
| 会话上限 | SA 入口 | SA→Scheduler→NAPI | reject 35700001 |
| 超时 | SA 定时器 | SA kill→Scheduler→NAPI + ErrorEvent | reject/终态 + 错误事件 |
| SA 不可用 | 客户端 | cli_tool_client→NAPI | reject 35700000 |
### 资源所有权矩阵
| 资源 | 创建方 | 持有方 | 销毁触发 | 实际释放 | 异常回收 |
|------|--------|--------|----------|----------|----------|
| 子进程 | ProcessManager | SessionRecord | 进程退出/超时/clear | Killpg + reap | 超时定时器 kill |
| 管道 fd(stdin/stdout/stderr) | ProcessManager | SessionRecord | 输出排空/会话清理 | close | IOMonitor 注销 + close |
| 会话记录 | SA | sessions_ 表 | 终态派发后 | RemoveSessionRecord | 超时/清理路径兜底移除 |
| Scheduler Stub | cli_tool_client | client 单例 | DeathRecipient | ClearProxy | 进程死亡清代理 |
| yield/timeout 定时器 | SA(IOMonitor 注册) | ffrt | 触发或会话清理 | ffrt 任务完成 | 会话清理时不取消(幂等检查 record 存在性) |
### 接口参数规约
| 接口 | 参数 | 类型 | 合法范围 | 非法处理 | 边界说明 |
|------|------|------|----------|----------|----------|
| execTool | toolName | string | 非空 + 已注册 | 空/非串→同步抛错;未注册→reject 35700005 | — |
| execTool | subcommand | string | 可空串 + 工具子命令表内 | 非空但工具无子命令/不在表→reject 35700005 | 空串用工具顶层 inputSchema |
| execTool | args | object | 键须在 inputSchema.properties 内且类型匹配 | 含未声明键/类型不符→reject 35700002 | 空对象合法;`help` 须单独存在 |
| execTool | challenge | string | 非空 | 空/非串→同步抛错 | — |
| ExecOptions | background | boolean | true/false | — | 默认 false |
| ExecOptions | yieldMs | int64 | ≥0;非后台须 ≤ timeout*1000 | <0 或越界→reject 35700002 | 默认 0;仅前台生效 |
| ExecOptions | timeout | int64 | ∈[0,1800] 秒 | <0 或 >1800→reject 35700002 | 默认 0=不启用;timeoutMs=timeout*1000 |
### 线程与并发模型
| 操作 | 发起线程 | 回调线程 | 跨进程边界 | 线程安全 | 重入约束 |
|------|----------|----------|------------|----------|----------|
| execTool(NAPI) | JS 主线程 | NapiAsyncTaskJsCliEventHandlerManager 投递) | 是(IPC | NAPI 异步任务串行化 | 允许并发调用 |
| SA ExecTool | Binder 线程 | ffrt 定时器线程 | 是 | sessions_ 表 ffrt::mutex 保护 | 允许并发会话 |
| IOMonitor 回调 | IOMonitor 线程 | 同 | 否(进程内) | SessionRecord 原子状态 + mutex | 幂等:record 不存在即跳过 |
**并发场景:**
| 场景 | 竞争对象 | 保护机制 | 预期行为 |
|------|----------|----------|----------|
| 多调用方并发创建会话 | sessions_ 表 | sessionsMutex_ 互斥 + 上限校验 | 超限拒绝 35700001 |
| 超时与正常退出竞争 | SessionRecord 状态 | 原子状态 + BeginCleanup 单次进入 | 仅一方完成终态派发 |
| 回调与代理死亡竞争 | Scheduler 代理 | DeathRecipient + mutex | 代理死亡不清会话,仅清代理 |
### 安全基础检查
> proposal「安全与权限」= 是,本节必填。
#### 信任边界交叉分析
| 边界类型 | 跨越的交互 | 风险 | 约束 |
|---|---|---|---|
| 用户态/内核态 | fork 子进程、pipe 读写 | 子进程越权 | 子进程运行在调用方 HAP 沙箱;SA 持 caps=KILL 可终止 |
| 沙箱内外 | 子进程 vs SA(aimgr) 进程 | 跨沙箱数据泄漏 | 沙箱配置按调用方 Token 生成;stdin/stdout/stderr 经管道受控 |
| 本地/远程 | NAPI→IPC→SA 全本地 | 无远程暴露 | 仅本机系统应用可调 |
| 不同 SELinux 域 | aimgr 域 vs 子进程域 | 域切换 | SA 域 aimgr;子进程域由沙箱配置决定 |
#### 基础安全要求
| 检查项 | 结论 | 说明/措施 |
|---|---|---|
| 加密算法(OH 推荐) | N/A | execTool 不涉及加密 |
| 密钥管理 | N/A | 不涉及密钥 |
| 随机数 | sessionId 生成 | 由 ToolUtil::GenerateCliSessionId 生成,不要求密码学随机 |
| 输入验证 | 强制 | toolName/subcommand/schema/timeout/yieldMs 全链路校验,非法即拒绝 |
| 错误处理 | 错误码化 | 357000xx 区间,不泄漏内部栈 |
| 配置 | 系统配置 | 并发上限由系统配置,非调用方可控 |
| 敏感数据处理(传输/存储/日志) | 不存储敏感数据 | 会话内存态;日志不打印 args 明文(args 仅 Key 校验) |
### 深度威胁分析(如需)
> 命中高风险判据评估:execTool 涉及沙箱/子进程/权限,但无网络暴露、无认证授权(仅本机系统应用+权限)、无敏感数据存储、无合规强约束。判定为不升级独立 threat-model.md。如 Owner 复核认为子进程沙箱逃逸风险需深入,再由 `ohos-security-threat-model` 产出。
## 风险和开放问题
| 项 | 类型 | 影响 | 处理方式 | Owner |
|----|------|------|----------|-------|
| 目标版本/Owner 未确认 | 进度 | 基线无法冻结为「通过」 | 需求方/SIG 确认 | 待确认 |
| d.ts 位置/SysCap 未确认 | API | 影响 @since 与 SysCap 声明 | API 评审 | 待确认 |
| `ohos.permission.EXEC_CLI_TOOL` 权限登记仓 | 构建 | 权限须在定义仓声明 | 跨仓协调 | 待确认 |
| yield/timeout 定时器在会话清理后触发 | 可靠性 | 幂等检查 record 存在性,已缓解 | 代码评审 + 单测 | — |
## 设计审批
- [x] 需求基线已确认,设计覆盖 P0/P1 ACAC-1.11.15
- [x] 不涉及项已承接,N/A 和展开项都有结论
- [x] 涉及仓和模块职责清楚
- [x] 调用链层级分析完整,每层覆盖到位
- [x] 适用架构规则已识别并形成设计结论
- [x] 分层和子系统边界合规
- [x] API 变更有签名、权限、错误码和兼容性说明
- [x] BUILD.gn/bundle.json 影响明确(无新增源文件,固化契约)
- [x] 设计输出和后续 Task 拆分明确
- [x] 关键设计决策有理由和影响说明
- [x] 风险和开放问题有 Owner(部分待确认)
**结论:** 条件通过(待 Owner 复核后转「通过」)
@@ -0,0 +1,626 @@
# 执行计划
> 将 Approved Spec 拆成可独立执行、可验证、可审查的 Task。本计划针对 `execTool` 既有实现进行契约固化与测试覆盖验证:实现已存在,Task 聚焦「验证既有链路符合 spec + 补齐测试缺口 + 跨仓协调」。
## Plan 元数据
| 字段 | 内容 |
|------|-----|
| Plan ID | PLAN-CLI-001 |
| 关联 Feature/Bug | FEAT-CLI-001REQ-010 |
| 关联文档 | proposal.md / design.md / spec.md |
| 复杂度 | 标准 |
| 状态 | Draft |
| Owner | 待确认 |
## 输入状态
| 输入 | 路径 | 要求状态 |
|------|------|----------|
| Requirement | `proposal.md` | Approved(条件通过,待 Owner 转正) |
| Design | `design.md` | Approved(条件通过,待 Owner 转正) |
| Spec | `spec.md` | ApprovedDraft→待转 Approved |
## 受影响文件全量清单
| 仓 | 层(来自 design.md) | 文件路径 | 修改类型 | 说明 |
|----|---------------------|----------|----------|------|
| ability_runtime | NAPI | `cli_tool_framework/frameworks/js/napi/cli_tool_manager/src/js_cli_manager.cpp` | 验证/补测试 | `execTool`/`OnExecTool` 参数解析与回调 |
| ability_runtime | NAPI | `cli_tool_framework/frameworks/js/napi/cli_tool_manager/include/js_cli_manager.h` | 只读参考 | 声明 |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/ICliToolManager.idl` | 只读参考 | `ExecTool` oneway 声明 |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/ICliToolManagerScheduler.idl` | 只读参考 | `SchedulerExecToolReplyEvent` 回复 |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/include/exec_tool_param.h` | 验证 | ExecToolParam Parcelable |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/include/exec_options.h` | 验证 | ExecOptions |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/include/cli_session_info.h` | 验证 | CliSessionInfo |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/include/exec_result.h` | 验证 | ExecResult |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/include/cli_error_code.h` | 验证 | 错误码 357000xx |
| ability_runtime | InnerAPI/IPC | `cli_tool_framework/interfaces/cli_tool/src/cli_tool_mgr_client.cpp` | 验证 | 客户端 ExecTool + SA 拉起 |
| ability_runtime | 服务 | `cli_tool_framework/services/climgr/src/cli_tool_manager_service.cpp` | 验证 | 服务端 ExecTool 全链路 |
| ability_runtime | 服务 | `cli_tool_framework/services/climgr/src/tool_util.cpp` | 验证 | 参数/schema/沙箱校验 |
| ability_runtime | 服务 | `cli_tool_framework/services/climgr/src/process_manager.cpp` | 验证 | 子进程创建 |
| ability_runtime | 服务 | `cli_tool_framework/services/climgr/src/session_record.cpp` | 验证 | 会话状态机 |
| ability_runtime | 服务 | `cli_tool_framework/services/climgr/src/event_dispatcher.cpp` | 验证 | 事件/回复派发 |
| ability_runtime | DFX | `cli_tool_framework/services/common/src/cli_event_report*.cpp` | 验证 | HiSysEvent 上报 |
| ability_runtime | SA | `services/sa_profile/186.json` | 只读参考 | SA 186 注册 |
| ability_runtime | 配置 | `cli_tool_framework/etc/profile/aimgr.cfg` | 只读参考 | 进程/权限/caps |
| 跨仓(权限定义仓) | 权限 | `ohos.permission.EXEC_CLI_TOOL` 定义 | 跨仓协调 | 权限登记(不在本仓) |
**检查项:**
- [x] design.md 调用链每一层都有对应文件列出
- [x] 每个文件修改类型和职责说明明确
- [x] 无映射行的层缺失
## AC 到 Task 追溯
| AC | 来源 | Task | 验证方式 | 覆盖? |
|----|------|------|----------|--------|
| AC-1.1 | spec.md | TASK-CLI-001 | 集成 | 是 |
| AC-1.2 | spec.md | TASK-CLI-002 | 集成 | 是 |
| AC-1.3 | spec.md | TASK-CLI-002 | 集成 | 是 |
| AC-1.4 | spec.md | TASK-CLI-003 | 集成 | 是 |
| AC-1.5 | spec.md | TASK-CLI-004 | 单测 | 是 |
| AC-1.6 | spec.md | TASK-CLI-004 | 单测 | 是 |
| AC-1.7 | spec.md | TASK-CLI-005 | 单测 | 是 |
| AC-1.8 | spec.md | TASK-CLI-005 | 单测 | 是 |
| AC-1.9 | spec.md | TASK-CLI-005 | 单测 | 是 |
| AC-1.10 | spec.md | TASK-CLI-005 | 单测 | 是 |
| AC-1.11 | spec.md | TASK-CLI-005 | 单测 | 是 |
| AC-1.12 | spec.md | TASK-CLI-006 | 单测 | 是 |
| AC-1.13 | spec.md | TASK-CLI-007 | 集成 | 是 |
| AC-1.14 | spec.md | TASK-CLI-004 | 集成 | 是 |
| AC-1.15 | spec.md | TASK-CLI-008 | 单测 | 是 |
## 首批实现边界
**首批必须实现:** TASK-CLI-001(正常链路)+ TASK-CLI-005(参数/边界校验)+ TASK-CLI-004(权限/非HAP),构成主链与安全边界。
**可后置:** TASK-CLI-008DFX 跨仓协调)。
**不建议延后:** TASK-CLI-002/003(会话语义/超时)延后会导致主链行为不闭合。
## 阶段计划(如适用)
| 阶段 | 目标 | 关键 Task | 结束门槛 | 最小验证 |
|------|------|-----------|----------|----------|
| Phase-1 | 主链+安全+参数 | TASK-CLI-001,004,005,006 | 正常执行与异常路径单测通过 | `run -t UT -ts cli_tool_mgr_client_test` |
| Phase-2 | 会话语义+超时+并发 | TASK-CLI-002,003,007 | yield/background/timeout/上限验证通过 | `run -t UT -ts process_manager_test` |
| Phase-3 | DFX+SA 不可用 | TASK-CLI-008 | 失败上报与 SA 不可用覆盖 | `run -t UT -ts cli_event_report_test` |
## Task 粒度原则
- 每个 Task 对应一个可独立验收的最小能力闭环
- 文件范围、验证闭环和风险边界足够分离 → 拆分
- 简单变更:1-2 张 Task Card;本计划按主链/会话/超时/权限/参数/NAPI/并发/DFX 拆为 8 张
- 每个 Task 自包含,不依赖外部文件路径引用
## 禁止项
- [x] 没有 TBD / TODO / 占位符(「待确认」为需 Owner 决议项,非规格占位)
- [x] 没有"根据需要实现""酌情处理"等模糊指令
- [x] 没有跨 Task 隐式依赖(依赖显式声明在前置依赖列)
- [x] 没有要求 Agent 自行寻找未列出的上下文文件
- [x] 没有无验证方式的 AC
- [x] 没有"与 Task-N 类似""参考 Task-N 实现"等引用
## Task 列表
| Task ID | 目标 | 文件范围 | AC 映射 | 前置依赖 | 完成判据 | 验证命令 |
|---------|------|----------|---------|----------|----------|----------|
| TASK-CLI-001 | 正常执行链路契约验证 | climgr/cli_tool_mgr_client | AC-1.1 | 无 | 正常调用返回 completed 会话与退出码 | `run -t UT -ts cli_tool_mgr_service_test` |
| TASK-CLI-002 | 前台让出/后台会话语义验证 | cli_tool_manager_service/session_record | AC-1.2,AC-1.3 | TASK-CLI-001 | yieldMs 与 background reply 时机/状态正确 | `run -t UT -ts cli_tool_mgr_service_test` |
| TASK-CLI-003 | 超时终止与终态派发验证 | cli_tool_manager_service/process_manager | AC-1.4 | TASK-CLI-002 | timeout 触发 kill+timeout=true+错误事件 | `run -t UT -ts process_manager_test` |
| TASK-CLI-004 | 权限/非HAP异常路径验证 | cli_tool_manager_service/cli_tool_mgr_client | AC-1.5,AC-1.6,AC-1.14 | TASK-CLI-001 | 非系统/缺权限/非HAP 返回正确码 | `run -t UT -ts cli_tool_mgr_client_test` |
| TASK-CLI-005 | 工具/子命令/schema/超时边界校验验证 | tool_util/exec_options/exec_tool_param | AC-1.71.11 | TASK-CLI-001 | 各非法输入返回 35700005/35700002 | `run -t UT -ts tool_util_test` |
| TASK-CLI-006 | NAPI 参数同步校验验证 | js_cli_manager | AC-1.12 | TASK-CLI-001 | 必填缺失/类型错/argc<4 同步抛错 | `run -t UT -ts cli_tool_mgr_client_test` |
| TASK-CLI-007 | 会话并发上限验证 | cli_tool_manager_service | AC-1.13 | TASK-CLI-001 | 超上限返回 35700001 | `run -t UT -ts cli_tool_mgr_service_test` |
| TASK-CLI-008 | DFX 失败上报 + SA 不可用验证 | cli_event_report/cli_tool_mgr_client | AC-1.15 | TASK-CLI-004 | SA 不可用返回 35700000;失败经 HiSysEvent | `run -t UT -ts cli_event_report_test` |
## Task 详情
### TASK-CLI-001: 正常执行链路契约验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证既有 execTool 正常链路符合 spec AC-1.1:合法调用返回 completed 会话与退出码 |
| AC 映射 | AC-1.1 |
| 前置依赖 | 无 |
| 非目标 | 不验证 yield/background/timeout(属 TASK-CLI-002/003 |
| 完成判据 | 集成测试覆盖:合法 toolName+subcommand+args+challenge→resolve status="completed"result.exitCode=进程退出码 |
| 停止条件 | 发现既有实现与 spec 行为不一致且无法在 Task 范围内修复 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/cli_tool_mgr_service_test/` | 正常链路用例 |
| Test | `cli_tool_framework/test/unittest/process_manager_test/` | 子进程创建用例 |
**Spec Context**
AC-1.1WHEN 系统应用持 EXEC_CLI_TOOL 调用 execTool,传入已注册 toolName、工具支持 subcommand、符合 inputSchema 的 args、非空 challenge THEN 接口返回 Promise,工具执行结束后 resolve 为 CliSessionInfo(status="completed"result.exitCode 等于子进程退出码)。
R-1:合法输入→创建会话与受沙箱子进程执行工具,结束后 resolve CliSessionInfo{status="completed", result.exitCode=进程退出码, outputText, errorText, executionTime}。
**Design Context**
调用链:NAPI→cli_tool_client Proxy→SA 186 ExecTool(oneway)→权限/查找/校验/沙箱→ProcessManager.CreateChildProcess→IOMonitor.RegisterSession→EventDispatcher.DispatchExecToolReplyEvent→client Scheduler Stub→NapiAsyncTask.Resolve。设计 ADR-1SA 集中承载)、ADR-2oneway+回调)。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-LAYERING | MustNAPI 不直接调 services 内部;经 InnerAPI/IPC |
| OH-ARCH-IPC-SAF | MustExecTool 为 oneway;回复经 Scheduler |
**Steps**
- [ ] 写失败测试:合法调用断言 resolve completed + exitCode
- [ ] 运行测试,确认当前结果
- [ ] 若不一致,做最小实现修正
- [ ] 运行测试,确认通过
- [ ] 填写完成证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts cli_tool_mgr_service_test` | PASS |
| 测试 | `run -t UT -ts process_manager_test` | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证 execTool 正常链路返回 completed 会话与退出码(AC-1.1 |
| 允许修改 | `cli_tool_framework/services/climgr/src/cli_tool_manager_service.cpp``cli_tool_framework/test/unittest/cli_tool_mgr_service_test/` |
| 允许新建 | 测试用例文件 |
| 只读参考 | `spec.md` AC-1.1、`design.md` ADR-1/ADR-2、`ICliToolManager.idl` |
| Spec 摘要 | AC-1.1 + R-1:合法输入→completed 会话+exitCode |
| Design 摘要 | NAPI→IPC→SA oneway+Scheduler 回复;ProcessManager.CreateChildProcess |
| 执行步骤 | 写失败测试→运行→最小修正→运行通过→记录证据 |
| 验证命令 | `run -t UT -ts cli_tool_mgr_service_test` / 期望: PASS |
| 完成规则 | 不得修改允许范围外文件;如需扩大范围停止并修订 Plan;无 fresh evidence 不得声明完成 |
### TASK-CLI-002: 前台让出/后台会话语义验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证 yieldMs 让出与 background 立即返回的 reply 时机与 status 符合 AC-1.2/AC-1.3 |
| AC 映射 | AC-1.2, AC-1.3 |
| 前置依赖 | TASK-CLI-001 |
| 非目标 | 不验证超时终止(TASK-CLI-003 |
| 完成判据 | background=true 立即 resolve runningforeground+yieldMs>0 在 yieldMs 处 resolve running 且转后台 |
| 停止条件 | 定时器或状态机行为与 spec 不一致且超范围 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/cli_tool_mgr_service_test/` | 会话语义用例 |
| Test | `cli_tool_framework/test/unittest/session_record_test/` | 状态机用例 |
**Spec Context**
AC-1.2WHEN background=false 且 yieldMs>0 THEN 在 yieldMs 毫秒后 resolve 为 status="running",会话转后台继续运行。
AC-1.3WHEN background=true THEN 立即 resolve 为 status="running"。
R-2/R-3yield 让出、background 立即返回。
**Design Context**
RegisterSessionWithMonitors:非 background 且 yieldMs!=0 → PostExecToolTask(yieldMs, isTimeout=false)background → HandleBackgroundSessionReply 立即派发。HandleProcessYieldTimeout 切后台并派发 running。状态机 SPAWNING→RUNNING→CANCELLING/COMPLETED/FAILED。设计 ADR-3。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-IPC-SAF | Must:回复经 SchedulerExecToolReplyEvent |
**Steps**
- [ ] 写失败测试:background 立即返回 + yieldMs 让出时机
- [ ] 运行测试
- [ ] 最小修正
- [ ] 运行通过
- [ ] 记录证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts cli_tool_mgr_service_test` | PASS |
| 测试 | `run -t UT -ts session_record_test` | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证 yield 让出与 background 立即返回语义(AC-1.2/1.3 |
| 允许修改 | `cli_tool_manager_service.cpp``session_record.cpp`、对应测试 |
| 允许新建 | 测试用例 |
| 只读参考 | spec AC-1.2/1.3、design ADR-3、`session_record.h` 状态枚举 |
| Spec 摘要 | AC-1.2/1.3 + R-2/R-3 |
| Design 摘要 | RegisterSessionWithMonitors 调度 yieldHandleBackgroundSessionReply/HandleProcessYieldTimeout |
| 执行步骤 | 写失败测试→运行→修正→通过→证据 |
| 验证命令 | `run -t UT -ts cli_tool_mgr_service_test` / 期望: PASS |
| 完成规则 | 不改范围外文件;无 evidence 不声明完成 |
### TASK-CLI-003: 超时终止与终态派发验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证 timeout 秒后进程被终止、result.timeout=true、派发超时错误事件(AC-1.4 |
| AC 映射 | AC-1.4 |
| 前置依赖 | TASK-CLI-002 |
| 非目标 | 不验证正常完成路径 |
| 完成判据 | 进程达 timeout 被 kill,终态 result.timeout=true,订阅者收到 "session timed out" 错误事件 |
| 停止条件 | kill/定时器逻辑与 spec 不一致且超范围 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/process_manager_test/` | 超时/kill 用例 |
**Spec Context**
AC-1.4WHEN 进程运行达 options.timeout 秒 THEN 进程被终止、result.timeout=true,并向订阅者派发超时错误事件。
R-4timeout>0 达阈值→终止、timeout=true、错误事件;未后台则派发终态 reply。
**Design Context**
PostExecToolTask(timeoutMs, isTimeout=true) → HandleProcessTimeoutSetTimeout(true)、SetState(CANCELLING)、DispatchExecToolReplyEvent(未后台)、DispatchErrorEvent("session timed out")、ProcessManager.Killpg。设计 ADR-4ffrt 延时)。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-ERROR-LOG | Must:超时经 HiSysEvent ReportCliTimeout 上报 |
**Steps**
- [ ] 写失败测试:timeout 触发 kill + timeout=true + 错误事件
- [ ] 运行测试
- [ ] 最小修正
- [ ] 运行通过
- [ ] 记录证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts process_manager_test` | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证超时终止与终态派发(AC-1.4) |
| 允许修改 | `cli_tool_manager_service.cpp``process_manager.cpp`、对应测试 |
| 允许新建 | 测试用例 |
| 只读参考 | spec AC-1.4 + R-4、design ADR-4 |
| Spec 摘要 | AC-1.4timeout→kill+timeout=true+错误事件 |
| Design 摘要 | HandleProcessTimeout + Killpg + ffrt 延时任务 |
| 执行步骤 | 写失败测试→运行→修正→通过→证据 |
| 验证命令 | `run -t UT -ts process_manager_test` / 期望: PASS |
| 完成规则 | 不改范围外文件;无 evidence 不声明完成 |
### TASK-CLI-004: 权限/非HAP异常路径验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证非系统应用、缺权限、非 HAP 调用分别返回 35700008/35700007/35700003AC-1.5/1.6/1.14 |
| AC 映射 | AC-1.5, AC-1.6, AC-1.14 |
| 前置依赖 | TASK-CLI-001 |
| 非目标 | 不验证工具不存在/参数非法(TASK-CLI-005 |
| 完成判据 | 三类调用方均被正确拒绝并返回对应错误码,失败经 HiSysEvent 上报 |
| 停止条件 | 权限/沙箱判定与 spec 不一致 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/cli_tool_mgr_client_test/` | 权限/非HAP 用例 |
**Spec Context**
AC-1.5:非系统应用→reject 35700008。AC-1.6:缺权限→reject 35700007。AC-1.14:非 HAP→reject 35700003。
R-5/R-11。
**Design Context**
ValidateExecToolPermissionsIsSystemAppByFullTokenID→ERR_NOT_SYSTEM_APPVerifyAccessToken(EXEC_CLI_TOOL)→ERR_PERMISSION_DENIED。ValidateAndPrepareTool→GenerateSandboxConfig 失败→ERR_NOT_HAP。ReportCliExecuteFailed 上报。设计「安全基础检查」信任边界。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-API-LEVEL | MustSystem API + 系统应用 + EXEC_CLI_TOOL |
| OH-ARCH-ERROR-LOG | Must:失败经 HiSysEvent |
**Steps**
- [ ] 写失败测试:三类调用方断言对应错误码
- [ ] 运行测试
- [ ] 最小修正
- [ ] 运行通过
- [ ] 记录证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts cli_tool_mgr_client_test` | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证权限/非HAP 异常路径错误码(AC-1.5/1.6/1.14 |
| 允许修改 | `cli_tool_manager_service.cpp``cli_tool_mgr_client.cpp`、对应测试 |
| 允许新建 | 测试用例 |
| 只读参考 | spec AC-1.5/1.6/1.14 + R-5/R-11、design 安全基础检查 |
| Spec 摘要 | 非系统→35700008;缺权限→35700007;非HAP→35700003 |
| Design 摘要 | ValidateExecToolPermissions + GenerateSandboxConfig + ReportCliExecuteFailed |
| 执行步骤 | 写失败测试→运行→修正→通过→证据 |
| 验证命令 | `run -t UT -ts cli_tool_mgr_client_test` / 期望: PASS |
| 完成规则 | 不改范围外文件;无 evidence 不声明完成 |
### TASK-CLI-005: 工具/子命令/schema/超时边界校验验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证工具/子命令不存在、schema 不匹配、timeout/yieldMs 越界返回 35700005/35700002AC-1.71.11 |
| AC 映射 | AC-1.7, AC-1.8, AC-1.9, AC-1.10, AC-1.11 |
| 前置依赖 | TASK-CLI-001 |
| 非目标 | 不验证权限路径(TASK-CLI-004 |
| 完成判据 | 各非法输入返回正确错误码;空 args 合法;help 特殊键放行 |
| 停止条件 | 校验逻辑与 spec 不一致 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/tool_util_test/` | 工具/schema 校验 |
| Test | `cli_tool_framework/test/unittest/exec_options_test/` | timeout/yieldMs 边界 |
| Test | `cli_tool_framework/test/unittest/exec_tool_param_test/` | Parcelable + schema |
**Spec Context**
AC-1.7toolName 未注册→35700005。AC-1.8subcommand 非法→35700005。AC-1.9args 不符 schema→35700002。AC-1.10timeout<0 或 >1800→35700002。AC-1.11:非后台 yieldMs>timeout*1000→35700002。
R-6/R-7/R-8。
**Design Context**
ValidatePropertiessubcommand 非空但工具无子命令/不在表→ERR_TOOL_NOT_EXIST。ValidateExecOptionsPropertiestimeout<0/yieldMs<0/timeout>1800/yieldMs>timeout*1000→ERR_INVALID_PARAM。ValidateInputSchemaPropertiesargs 键须在 properties 且类型匹配;help 单独放行;空 args 合法。接口参数规约表。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-ERROR-LOG | Must:错误码 35700005/35700002 |
**Steps**
- [ ] 写失败测试:各非法输入断言错误码
- [ ] 运行测试
- [ ] 最小修正
- [ ] 运行通过
- [ ] 记录证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts tool_util_test` | PASS |
| 测试 | `run -t UT -ts exec_options_test` | PASS |
| 测试 | `run -t UT -ts exec_tool_param_test` | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证工具/子命令/schema/超时边界校验(AC-1.71.11 |
| 允许修改 | `tool_util.cpp``exec_options.cpp``exec_tool_param.cpp`、对应测试 |
| 允许新建 | 测试用例 |
| 只读参考 | spec AC-1.71.11 + R-6/R-7/R-8、design 接口参数规约 |
| Spec 摘要 | 工具/子命令→35700005schema/超时边界→35700002 |
| Design 摘要 | ValidateProperties + ValidateExecOptionsProperties + ValidateInputSchemaProperties |
| 执行步骤 | 写失败测试→运行→修正→通过→证据 |
| 验证命令 | `run -t UT -ts tool_util_test` / 期望: PASS |
| 完成规则 | 不改范围外文件;无 evidence 不声明完成 |
### TASK-CLI-006: NAPI 参数同步校验验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证必填缺失/类型错/argc<4 同步抛 invalid parameter 异常(AC-1.12 |
| AC 映射 | AC-1.12 |
| 前置依赖 | TASK-CLI-001 |
| 非目标 | 不验证服务端校验(TASK-CLI-005 |
| 完成判据 | toolName/challenge 空或非串、args 非对象、argc<4 均同步抛错,不进入异步 |
| 停止条件 | NAPI 校验与 spec 不一致 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/cli_tool_mgr_client_test/` | NAPI 校验用例 |
**Spec Context**
AC-1.12toolName 空/非串、challenge 空/非串、args 非对象、实参<4 → 同步抛 invalid parameter 异常。
R-9NAPI 层校验先于服务端。
**Design Context**
OnExecToolargc<INDEX_FOUR→ThrowTooFewParametersErrorUnwrapStringFromJS2(toolName) 失败或空→ThrowInvalidParamError("Tool toolName is required")subcommand 非串→抛错;UnwrapWantParams(args) 失败→抛错;challenge 空或非串→抛错;UnwrapExecOptions 失败→抛错。BindNativeFunction("execTool")。调用链层级 NAPI 层。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-LAYERING | MustNAPI 层做同步参数校验先于 IPC |
**Steps**
- [ ] 写失败测试:各缺失/类型错/argc<4 断言同步抛错
- [ ] 运行测试
- [ ] 最小修正
- [ ] 运行通过
- [ ] 记录证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts cli_tool_mgr_client_test` | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证 NAPI 参数同步校验(AC-1.12 |
| 允许修改 | `js_cli_manager.cpp`、对应测试 |
| 允许新建 | 测试用例 |
| 只读参考 | spec AC-1.12 + R-9、design 调用链 NAPI 层 |
| Spec 摘要 | 必填缺失/类型错/argc<4→同步抛错 |
| Design 摘要 | OnExecTool 参数解析与 ThrowInvalidParamError |
| 执行步骤 | 写失败测试→运行→修正→通过→证据 |
| 验证命令 | `run -t UT -ts cli_tool_mgr_client_test` / 期望: PASS |
| 完成规则 | 不改范围外文件;无 evidence 不声明完成 |
### TASK-CLI-007: 会话并发上限验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证活动会话数达系统上限时返回 35700001AC-1.13 |
| AC 映射 | AC-1.13 |
| 前置依赖 | TASK-CLI-001 |
| 非目标 | 不验证单会话内部行为 |
| 完成判据 | 会话数≥上限→reject 35700001,不排队 |
| 停止条件 | 并发保护与 spec 不一致 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/cli_tool_mgr_service_test/` | 上限用例 |
**Spec Context**
AC-1.13:会话数达上限→reject 35700001。
R-10:全局会话表 + 系统配置上限。
**Design Context**
ValidateSessionLimitGetCliConcurrencyLimit→sessions_ 表 size≥上限→ERR_SESSION_LIMIT_EXCEEDED。sessionsMutex_ 互斥保护。设计 ADR-5。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-ERROR-LOG | Must:错误码 35700001 |
**Steps**
- [ ] 写失败测试:填满会话后调用断言 35700001
- [ ] 运行测试
- [ ] 最小修正
- [ ] 运行通过
- [ ] 记录证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts cli_tool_mgr_service_test` | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证会话并发上限(AC-1.13) |
| 允许修改 | `cli_tool_manager_service.cpp`、对应测试 |
| 允许新建 | 测试用例 |
| 只读参考 | spec AC-1.13 + R-10、design ADR-5 |
| Spec 摘要 | 超上限→35700001 |
| Design 摘要 | ValidateSessionLimit + sessions_ mutex |
| 执行步骤 | 写失败测试→运行→修正→通过→证据 |
| 验证命令 | `run -t UT -ts cli_tool_mgr_service_test` / 期望: PASS |
| 完成规则 | 不改范围外文件;无 evidence 不声明完成 |
### TASK-CLI-008: DFX 失败上报 + SA 不可用验证
| 字段 | 内容 |
|------|-----|
| 任务目标 | 验证 SA 不可用返回 35700000AC-1.15);失败路径经 HiSysEvent 上报 bundleName/toolName/failureReason |
| AC 映射 | AC-1.15 |
| 前置依赖 | TASK-CLI-004 |
| 非目标 | 不验证正常路径 DFX |
| 完成判据 | SA 拉起失败/代理空→reject 35700000;失败路径 HiSysEvent 字段完整 |
| 停止条件 | DFX 事件与 hisysevent.yaml 定义冲突 |
**Files**
| 操作 | 文件 | 说明 |
|------|------|------|
| Test | `cli_tool_framework/test/unittest/cli_event_report_test/` | DFX 上报用例 |
| Test | `cli_tool_framework/test/unittest/cli_tool_mgr_client_test/` | SA 不可用用例 |
**Spec Context**
AC-1.15CliToolManager SA 未就绪/代理获取失败→reject 35700000。
R-12SA 未加载/代理空→35700000。
**Design Context**
cli_tool_client LoadCliToolMgrService 失败→GET_CLI_TOOL_MGR_SERVICE_FAILED。ReportCliExecuteFailed/ReportCliTimeout 上报 bundleName/toolName/failureReason/duration。hisysevent.yaml 为硬性合约。设计异常传播时序图。
**Required Rules**
| Rule ID | Must / Must Not |
|---------|-----------------|
| OH-ARCH-ERROR-LOG | Must:不破坏 hisysevent.yaml 已发布事件;不为通过测试删事件 |
| OH-ARCH-IPC-SAF | MustSA 按需拉起,失败回 35700000 |
**Steps**
- [ ] 写失败测试:SA 不可用断言 35700000;失败上报断言 HiSysEvent 字段
- [ ] 运行测试
- [ ] 最小修正
- [ ] 校验 hisysevent.yaml 未被破坏
- [ ] 运行通过
- [ ] 记录证据
**Completion Evidence**
| 证据类型 | 命令/路径 | 结果 |
|----------|-----------|------|
| 测试 | `run -t UT -ts cli_event_report_test` | PASS |
| 测试 | `run -t UT -ts cli_tool_mgr_client_test` | PASS |
| 静态检查 | `hisysevent.yaml` 事件定义未被破坏 | PASS |
**Handoff Summary**
| 项 | 内容 |
|----|------|
| 任务描述 | 验证 SA 不可用 35700000 + 失败 HiSysEvent 上报(AC-1.15 |
| 允许修改 | `cli_event_report*.cpp``cli_tool_mgr_client.cpp`、对应测试 |
| 允许新建 | 测试用例 |
| 只读参考 | spec AC-1.15 + R-12、design 异常传播时序图、`hisysevent.yaml` |
| Spec 摘要 | SA 不可用→35700000;失败经 HiSysEvent |
| Design 摘要 | LoadCliToolMgrService + ReportCliExecuteFailed/ReportCliTimeout |
| 执行步骤 | 写失败测试→运行→修正→校验 yaml→通过→证据 |
| 验证命令 | `run -t UT -ts cli_event_report_test` / 期望: PASS |
| 完成规则 | 不改 hisysevent.yaml 已发布事件;不改范围外文件;无 evidence 不声明完成 |
## Plan 自审清单
- [x] 每个 P0/P1 AC 至少映射到一个 TaskAC-1.11.15 全覆盖)
- [x] 每个 Task 文件范围明确
- [x] 每个 Task 明确前置依赖、非目标、完成判据和停止条件
- [x] 每个 Task 有验证命令
- [x] Task 粒度形成能力闭环
- [x] 没有 TBD/TODO/占位符(「待确认」为 Owner 决议项)
- [x] 没有要求 Agent 自行寻找未列出的上下文
- [x] 交接信息自包含(Handoff Summary 完整)
- [x] 每个 Task 验证在完成时立即执行并记录证据
- [x] 超 3000 行阈值的 Task 已说明不拆分理由(本计划 Task 均聚焦验证+补测试,上下文未超阈值)
@@ -0,0 +1,301 @@
---
target_release:
id: OpenHarmony-6.0-Release
status: proposed
---
# 需求文档
> 一份文档,从原始需求到基线结论。本需求 `REQ-010` 原始条目未在工作区检索到,以下内容依据 `cli_tool_framework` 中 `execTool` 既有实现反推并固化,待需求方/Owner 确认后基线。
## 一、原始需求
### 基本信息
| 字段 | 内容 |
|------|------|
| 需求ID | REQ-010 |
| 需求名称 | 执行 CLI 工具(execToolSystem API |
| 来源 | 待确认(实现已存在于 cli_tool_framework2026 版权) |
| 提出人 | 待确认 |
| 目标发行版本 | OpenHarmony-6.0-Release(待确认) |
| 候选 Profile | none |
| 优先级 | P1 |
| 状态 | Clarifying |
### 原始描述
**原始问题:** 系统应用需要一种受控、受沙箱约束的方式按名称执行系统中已注册的命令行工具(CLI Tool),并获取执行会话的状态与结果,而不应直接 fork 任意命令或绕过权限审计。
**痛点:**
| 用户类型 | 当前痛点 | 影响 |
|----------|----------|------|
| 系统应用开发者 | 无统一受控入口执行已注册 CLI 工具,需自建子进程与权限处理 | 集成成本高、安全风险大 |
| 系统安全/审计方 | 缺少统一的权限校验、沙箱隔离与失败上报 | 故障归因与合规审计困难 |
| 平台方 | 工具执行无并发上限与超时控制 | 易被滥用导致资源耗尽 |
**期望结果:** 系统应用通过一个 System API(`execTool`)执行已注册 CLI 工具,系统统一完成权限校验、沙箱子进程创建、超时/让出/后台会话管理与结果回传,并在失败路径经 HiSysEvent 上报。
### 背景证据
| 证据类型 | 链接/路径 | 说明 |
|----------|-----------|------|
| 源码实现 | `cli_tool_framework/frameworks/js/napi/cli_tool_manager/src/js_cli_manager.cpp` | NAPI 入口 `execTool`/`OnExecTool` 已实现 |
| 源码实现 | `cli_tool_framework/services/climgr/src/cli_tool_manager_service.cpp` | 服务端 `ExecTool`、超时/让出/会话管理已实现 |
| SA 注册 | `services/sa_profile/186.json` | SA 186(进程 aimgr,库 libclimgr.z.so |
| 进程配置 | `cli_tool_framework/etc/profile/aimgr.cfg` | ondemand、uid=aimgr、caps=KILL、SELinux 域 aimgr |
### 初始范围
**可能包含:**
- `execTool` System API 的参数契约(toolName/subcommand/args/challenge/options
- 前台/让出(yieldMs)/后台/超时 四种会话语义
- 权限校验(系统应用 + `ohos.permission.EXEC_CLI_TOOL`)、HAP 沙箱校验
- 错误码 3570000035700008、35700020
**明确不包含:**
- `execCmd`shell 命令执行)、`SubscribeSession`/`SendMessage`/`RegisterFunction` 等同模块其他接口
- 工具注册/数据管理(`CliToolDataManager`/`RegisterFunction`)的内部实现
- 跨设备会话同步
### 初始假设
| 假设 | 类型 | 验证方式 | 状态 |
|------|------|----------|------|
| 调用方须为系统应用 HAP | 技术/安全 | 源码 `ValidateExecToolPermissions` | 已验证 |
| 沙箱由系统按调用方 Token 生成 | 技术 | 源码 `ToolUtil::GenerateSandboxConfig` | 已验证 |
| 会话为运行态内存对象,不持久化 | 兼容性 | 源码 `SessionRecord` 生命周期 | 已验证 |
| 并发上限由系统配置决定 | 技术 | 源码 `CcmUtil::GetCliConcurrencyLimit` | 已验证 |
### 初始分级判断
| 判断项 | 结果 | 依据 |
|--------|------|------|
| 复杂度 | 标准 | 单 System API,行为分支有限但涉及沙箱/IPC/会话生命周期 |
| 涉及仓数量 | 1 | `foundation/ability/ability_runtime` |
| 是否涉及 Public/System API | 是 | 新增 System API `execTool` |
| 是否涉及安全/性能关键路径 | 是 | 权限校验、沙箱、子进程、超时 |
| 是否跨 SIG | 否 | 全部在 Sig-Ability 内 |
### 进入澄清条件
- [x] 原始问题和期望结果已记录
- [ ] 需求来源和责任人已明确(待确认)
- [x] 初始范围和不包含项已记录
- [x] 关键假设和待澄清问题已列出
- [x] 复杂度有判断或明确为待定
---
## 二、澄清记录
> 本需求无原始对话记录,澄清项依据实现反推。标记「已澄清(实现反推)」的项需 Owner 复核确认。
### 待澄清问题
| 编号 | 问题 | 为什么需要澄清 | 状态 |
|------|------|----------------|------|
| Q-1 | `execTool` 是否仅限系统应用? | 决定 API 开放范围与权限模型 | 已澄清(实现反推:仅系统应用) |
| Q-2 | 是否允许非 HAP 调用? | 决定沙箱生成可行性 | 已澄清(实现反推:须 HAP) |
| Q-3 | 让出(yieldMs)与后台(background)是否互斥? | 决定会话语义模型 | 已澄清(实现反推:yieldMs 仅前台生效) |
| Q-4 | 超时上限是否固定 1800 秒? | 决定边界约束 | 已澄清(实现反推:MAX_TIMEOUT=1800 |
| Q-5 | 目标发行版本? | 基线必需 | 待确认 |
### 讨论记录
| 日期 | 参与人 | 讨论主题 | 结论 | 后续动作 |
|------|--------|----------|------|----------|
| 2026-08-05 | AI 反推 | 会话语义 | 前台/让出/后台/超时四态 | Owner 复核 |
### 功能范围确认
| 问题 | 回答 | 确认人 | 状态 |
|------|------|--------|------|
| 核心功能包含哪些? | execTool 执行已注册 CLI 工具;前台/让出/后台/超时会话;错误码 | 待确认 | 已确认(反推)/待确认 |
| 明确不包含哪些? | execCmd、订阅、注册函数、跨设备同步 | 待确认 | 已确认(反推)/待确认 |
| 是否有分期策略? | 否 | 待确认 | 已确认(反推) |
### 方案探索
| 编号 | 方案概述 | 优势 | 风险/代价 | 选择结论 |
|------|----------|------|-----------|----------|
| A-1 | SA186/aimgr)统一承载:NAPI→IPC→服务端做权限/沙箱/子进程/会话管理 | 集中权限审计、统一沙箱、可并发控制、失败可上报 | 跨进程 IPC 开销、SA 须按需拉起 | 推荐 |
| A-2 | 应用进程内直接 fork+exec 工具 | 无 IPC 开销、延迟低 | 绕过权限审计、沙箱不可控、无并发上限、难审计 | 放弃 |
**取舍理由:** CLI 工具执行涉及权限/沙箱/超时/审计,集中到 SA 可统一安全边界与并发控制,IPC 开销可接受;A-2 安全风险不可接受。
### 上下文与知识源检索日志
| 编号 | 来源 | 查询/读取内容 | 关键发现 | 可信度 | 用于 | 命中/原因 |
|------|------|---------------|----------|--------|------|-----------|
| K-1 | 源码 `js_cli_manager.cpp` | `OnExecTool` 参数解析与回调派发 | 必填:toolName/subcommand/args/challengeoptions 可选;argc<4 同步抛错 | 高 | 范围/API | 命中 |
| K-2 | 源码 `cli_tool_manager_service.cpp` | `ExecTool`/`ValidateExecToolPermissions`/`ValidateAndPrepareTool`/`SetupAndStartSession`/超时与让出处理 | 权限链、会话生命周期、超时=1800、yieldMs 仅前台、后台立即返回 | 高 | 设计/测试 | 命中 |
| K-3 | 源码 `tool_util.cpp` | `ValidateProperties`/`ValidateExecOptionsProperties`/`ValidateInputSchemaProperties` | subcommand 与 inputSchema 校验规则、help 特殊键 | 高 | 设计/测试 | 命中 |
| K-4 | `cli_error_code.h` | 错误码枚举 | 3570000035700020 区间 | 高 | API | 命中 |
| K-5 | `ICliToolManager.idl` | IPC 接口签名 | `ExecTool(param, eventId, scheduler)` oneway 回复经 Scheduler | 高 | 设计 | 命中 |
| K-6 | `services/sa_profile/186.json``aimgr.cfg` | SA 注册与进程配置 | SA 186、进程 aimgr、ondemand、caps=KILL | 高 | 设计/构建 | 命中 |
| K-7 | `AGENTS.md` | 目标仓 Agent 指南 | 服务层与 SDK 层解耦、PermissionVerification、hisysevent 硬约束 | 高 | 设计约束 | 命中 |
**上下文结论:**
- 高可信结论:execTool 行为链路、参数契约、错误码、SA/进程模型均已由源码固化,可直接进入基线与设计。
- 待确认结论:目标发行版本、需求来源与责任人、并发上限具体数值(由产品配置)。
- 未使用来源及原因:未使用多仓知识库(本需求单仓内闭环)。
### 子系统影响
| 问题 | 回答 | 确认人 | 状态 |
|------|------|--------|------|
| 涉及哪些子系统? | abilityability_runtime | 待确认 | 已确认(反推) |
| 是否需要新增子系统或部件? | 否 | 待确认 | 已确认(反推) |
### API 变更评估
| 问题 | 回答 | 确认人 | 状态 |
|------|------|--------|------|
| 是否需要新增/修改 Public API? | 否 | 待确认 | 已确认(反推) |
| 是否需要新增 System API | 是,1 个(`execTool`) | 待确认 | 已确认(反推) |
| 是否会废弃已有 API? | 否 | 待确认 | 已确认(反推) |
| 是否需要新增权限声明? | 是,`ohos.permission.EXEC_CLI_TOOL` | 待确认 | 已确认(反推) |
### 兼容性与非功能需求
| 类别 | 核心问题 | 结论 | 确认人 | 状态 |
|------|----------|------|--------|------|
| 兼容性 | 向前/向后兼容要求?破坏性变更? | 新增 API,无破坏性;会话内存态无持久化迁移 | 待确认 | 已确认(反推) |
| 性能 | 响应时间/内存/并发要求? | 并发受系统上限约束;无公开 P 指标 | 待确认 | 已确认(反推) |
| 安全 | 权限/隐私/加密/审计要求? | 系统应用+权限+HAP 沙箱;失败经 HiSysEvent | 待确认 | 已确认(反推) |
| 可靠性 | 崩溃率/容错/恢复要求? | SA 不可用回 35700000;单次调用不应致 SA 崩溃 | 待确认 | 已确认(反推) |
### 依赖与风险
| 依赖项 | 类型 | 说明 | 状态 |
|--------|------|------|------|
| `safwk`/`samgr` | 编译/运行 | SA 186 按需注册与拉起 | 已确认 |
| `access_token` | 运行 | 系统应用判定与权限校验 | 已确认 |
| `bundle_framework` | 运行 | HAP 判定与 bundleName 获取 | 已确认 |
| `kv_store` | 运行 | 工具/函数元数据存储(不影响 execTool 行为契约) | 已确认 |
| 风险 | 类型 | 影响 | 缓解措施 | 状态 |
|------|------|------|----------|------|
| 需求来源/Owner 未确认 | 进度 | 基线无法冻结 | 需求方/SIG 确认 | 待确认 |
| 目标版本未确认 | 进度 | 影响 @since 与发布 | proposal.target_release 确认 | 待确认 |
| 并发上限随产品配置 | 技术 | 行为语义不变但数值差异 | spec 标注「由系统配置决定」 | 已确认 |
### AC 完整性
- [x] 每个用户故事有验收标准
- [x] AC 全部使用 WHEN/THEN 格式
- [x] 覆盖正常流程、异常流程、边界条件
- [x] AC 可测试、可度量
### 澄清结论
- [x] 功能范围已完全明确
- [x] 子系统影响已识别
- [x] API 变更已评估
- [x] 兼容性和非功能需求已确认
- [x] 依赖和风险已识别且有缓解方案
- [x] AC 完整可测试
- [x] 标准及以上复杂度已完成方案探索(A-1/A-2 + 取舍理由)
**结论:** 条件通过(实现反推完整,待 Owner/需求方确认后转「通过」)
---
## 三、需求基线
> 澄清完成后固化。manifest.md 是事实源,此处为审批结论。
### 基线信息
| 字段 | 内容 |
|------|-----|
| 基线版本 | v1.0 |
| 基线日期 | 2026-08-05 |
| Owner | 待确认 |
| 确认人 | 需求方/模块Owner/SIG代表(待确认) |
| 复杂度 | 标准 |
| Profile | none |
| 目标发行版本 | OpenHarmony-6.0-Release(待确认) |
| 版本状态 | proposed |
### 问题陈述
系统应用缺少受控、可审计、受沙箱约束的 CLI 工具执行入口。本需求新增 `execTool` System API,由 SA 186aimgr)统一承载权限校验、沙箱子进程创建、会话生命周期(前台/让出/后台/超时)与结果回传,并在失败路径经 HiSysEvent 上报。
### 目标和成功指标
| 目标 | 成功指标 | 验证方式 |
|------|----------|----------|
| 受控执行已注册 CLI 工具 | 合法调用返回 completed 会话与退出码 | 集成测试 |
| 权限/沙箱边界生效 | 非系统应用/缺权限/非 HAP 均被拒绝并返回正确错误码 | 单测 |
| 会话语义正确 | 前台/让出/后台/超时各态 reply 时机与 status 正确 | 集成测试 |
| 失败可归因 | 失败路径经 HiSysEvent 上报 bundleName/toolName/failureReason | hisysevent 校验 |
### 用户故事与 AC
| Story ID | 用户故事 | 优先级 |
|----------|----------|--------|
| US-1 | 作为系统应用开发者,我想要通过 execTool 按名称执行已注册 CLI 工具并获取会话信息,以便在系统应用内集成受沙箱约束的命令行工具能力 | P1 |
> AC 共 15 条(AC-1.1AC-1.15),详见 `spec.md`。此处不重复摘录,避免与 spec 不一致。
### 范围边界
**包含:** `execTool` System API 行为契约、参数校验、会话生命周期(前台/让出/后台/超时)、错误码、权限/沙箱前置校验。
**不包含:** `execCmd``SubscribeSession`/`SendMessage``RegisterFunction`、工具注册数据管理、跨设备同步。
### 影响范围
| 子系统 | 仓库 | 模块/路径 | 当前职责 | 影响类型 | Owner |
|--------|------|-----------|----------|----------|-------|
| ability | foundation/ability/ability_runtime | cli_tool_framework/frameworks/js/napi/cli_tool_manager | NAPI 绑定 | 新增 API(既有实现固化契约) | 待确认 |
| ability | foundation/ability/ability_runtime | cli_tool_framework/services/climgr | 服务端实现 | 新增(既有实现固化契约) | 待确认 |
| ability | foundation/ability/ability_runtime | cli_tool_framework/interfaces/cli_tool | IPC 接口与数据结构 | 新增(既有实现固化契约) | 待确认 |
| ability | foundation/ability/ability_runtime | services/sa_profile/186.json | SA 注册 | 不变(已注册) | — |
### API 变更项清单
| API 名称 | 变更类型 | 开放范围 | 概要说明 |
|----------|----------|----------|----------|
| `cliTool.execTool` | 新增 | System | 按名称执行已注册 CLI 工具,返回 Promise<CliSessionInfo> |
### 不涉及项确认
| 维度 | 涉及? | 依据 | 若涉及,进入哪个下游文档 |
|------|--------|------|--------------------------|
| 性能 | 否 | 无公开 P 指标;并发上限由系统配置,非本 API 行为契约 | — |
| 安全与权限 | 是 | 系统应用+EXEC_CLI_TOOL 权限、HAP 沙箱、失败上报 | design.md / spec.md |
| 兼容性 | 否 | 新增 API,无破坏性;会话内存态无迁移 | spec.md |
| API/SDK | 是 | 新增 System API | design.md / spec.md |
| IPC/跨进程 | 是 | NAPI→IPC→SA 186 | design.md |
| 构建与部件 | 否 | 复用既有 component/parts,无新增部件 | — |
| 国际化/无障碍 | 否 | 无界面 System API | — |
| 数据迁移 | 否 | 无持久化 | — |
### 变更控制
| 变更类型 | 触发条件 | 处理规则 |
|----------|----------|----------|
| 范围新增 | 新增用户故事或仓/模块 | 重新评估复杂度和设计影响 |
| AC 变更 | 修改可观察行为或错误码 | 重新审批基线和 Spec |
| API 变更 | 新增/修改 Public/System API | 触发设计审批 |
| 非功能指标变更 | 性能/安全/兼容性阈值变化 | 重新确认测试计划 |
| 目标版本变更 | 交付版本调整 | 更新 proposal.target_release |
### 进入设计/Spec 条件
- [x] 所有 P0/P1 用户故事有 AC
- [x] 每条 AC 可测试、可度量
- [x] 范围内/外已确认
- [ ] `proposal.target_release` 已确认或明确 TBD(待确认)
- [x] `manifest.profile` 已确认或明确 none
- [x] 涉及仓、模块、SIG 已识别
- [x] 不涉及项已标记 N/A
- [x] 变更控制规则已确认
- [x] 标准及以上复杂度的澄清问题已逐项关闭,且讨论记录包含需求方/Owner/SIG 明确确认(实现反推,待 Owner 复核)
- [x] 上下文与知识源检索日志已填写;未查询关键来源的原因已记录
- [x] 目标仓 Agent 指南已检查并记录关键约束(AGENTS.md 服务/SDK 解耦、PermissionVerification、hisysevent 硬约束)
**基线结论:** 条件通过
@@ -0,0 +1,278 @@
# 特性规格
> 本规格仅覆盖 `execTool` 接口行为。范围限定:`execTool` 的用户可见行为、参数契约、错误码、会话生命周期与超时/让出/后台语义。`execCmd`、`SubscribeSession`、`SendMessage`、`RegisterFunction` 等同模块其他接口不在本规格范围内。
>
> **输入文档说明:** 工作区未检索到 `REQ-010` 需求条目与已批准的 `proposal.md`。本规格依据 `cli_tool_framework` 中 `execTool` 的既有实现(`frameworks/js/napi/cli_tool_manager/src/js_cli_manager.cpp`、`services/climgr/src/cli_tool_manager_service.cpp`、`interfaces/cli_tool/`)反推固化。待 `proposal.md` 基线化后,以下「优先级/目标版本/SIG 归属」字段应回填 proposal 值。
## 概述
| 属性 | 值 |
|------|-----|
| 特性名称 | 执行 CLI 工具(execTool |
| 特性编号 | FEAT-CLI-001 |
| 所属 Epic | REQ-010 |
| 优先级 | P1 |
| 目标版本 | 参见 proposal.md(待基线) |
| SIG 彾属 | Sig-Ability |
| 状态 | Draft |
| 复杂度 | 标准 |
## 本次变更范围(Delta
本特性为新增能力(lineage: new)。`execTool``cli_tool_framework` 对外暴露的 System API,此前不存在对外契约。
| 类型 | 内容 | 说明 |
|------|------|------|
| ADDED | `execTool` System API(JS | 系统应用按名称执行已注册 CLI 工具,返回会话信息 |
| ADDED | 错误码 3570000035700008、35700020 | 见 cli_error_code.h,本规格仅声明 execTool 链路涉及项 |
| ADDED | 权限 `ohos.permission.EXEC_CLI_TOOL` | execTool 调用前置权限 |
| ADDED | 数据结构 `ExecOptions`/`CliSessionInfo`/`ExecResult` | 对外行为契约,非内部实现 |
## 输入文档
| 文档 | 路径 | 状态 |
|------|------|------|
| Requirement | `REQ-010`(未在工作区检索到) | Pending |
| Proposal | `proposal.md`(未提供) | Pending |
> 需求基线、不涉及项、受影响子系统与仓库详见 proposal.md,本文档不重复摘录。design.md 与本文档并行产出,互不依赖。
## 用户故事
### US-1: 系统应用执行已注册的 CLI 工具
**作为** 系统应用开发者,
**我想要** 通过 `execTool` 接口按名称执行已注册的 CLI 工具并获取执行会话信息,
**以便** 在系统应用内集成受沙箱约束的命令行工具能力。
**验收标准(AC, Acceptance Criteria):**
| AC编号 | 验收标准 | 类型 |
|--------|----------|------|
| AC-1.1 | WHEN 系统应用持 `ohos.permission.EXEC_CLI_TOOL` 调用 `execTool`,传入已注册的 `toolName`、工具支持的 `subcommand`、符合工具 `inputSchema``args`、非空 `challenge` THEN 接口返回 Promise,工具执行结束后 resolve 为 `CliSessionInfo``status="completed"``result.exitCode` 等于子进程退出码) | 正常 |
| AC-1.2 | WHEN `options.background=false``options.yieldMs>0` THEN 在 `yieldMs` 毫秒后 resolve 为 `status="running"``CliSessionInfo`,会话转入后台继续运行 | 行为 |
| AC-1.3 | WHEN `options.background=true` THEN 接口立即 resolve 为 `status="running"``CliSessionInfo`,不等待执行结束 | 行为 |
| AC-1.4 | WHEN 进程持续运行至 `options.timeout` 秒 THEN 进程被终止、最终会话 `result.timeout=true`,并向会话订阅者派发超时错误事件 | 边界 |
| AC-1.5 | WHEN 非系统应用调用 `execTool` THEN Promise reject 错误码 `35700008`ERR_NOT_SYSTEM_APP | 异常 |
| AC-1.6 | WHEN 系统应用未持有 `ohos.permission.EXEC_CLI_TOOL` THEN Promise reject 错误码 `35700007`ERR_PERMISSION_DENIED | 异常 |
| AC-1.7 | WHEN `toolName` 未在系统中注册 THEN Promise reject 错误码 `35700005`ERR_TOOL_NOT_EXIST | 异常 |
| AC-1.8 | WHEN 传入非空 `subcommand` 但工具未声明子命令,或 `subcommand` 不在工具子命令列表中 THEN Promise reject 错误码 `35700005`ERR_TOOL_NOT_EXIST | 异常 |
| AC-1.9 | WHEN `args` 含工具 `inputSchema` 未定义的键,或某键值类型与 schema 声明不符 THEN Promise reject 错误码 `35700002`ERR_INVALID_PARAM | 异常 |
| AC-1.10 | WHEN `options.timeout<0``options.timeout>1800` THEN Promise reject 错误码 `35700002`ERR_INVALID_PARAM | 边界 |
| AC-1.11 | WHEN `options.background=false``options.yieldMs>options.timeout*1000` THEN Promise reject 错误码 `35700002`ERR_INVALID_PARAM | 边界 |
| AC-1.12 | WHEN `toolName` 为空字符串/非字符串、`challenge` 为空字符串/非字符串、`args` 非对象,或实参个数小于 4 THEN 同步抛出 invalid parameter 异常,不进入异步链路 | 边界 |
| AC-1.13 | WHEN 调用时系统并发会话数已达上限 THEN Promise reject 错误码 `35700001`ERR_SESSION_LIMIT_EXCEEDED | 边界 |
| AC-1.14 | WHEN 调用方进程非 HAP THEN Promise reject 错误码 `35700003`ERR_NOT_HAP | 异常 |
| AC-1.15 | WHEN CliToolManager 系统能力未就绪或代理获取失败 THEN Promise reject 错误码 `35700000`GET_CLI_TOOL_MGR_SERVICE_FAILED | 恢复 |
## 验收追溯
| AC | 关联规则 | 关联 Task | 验证方式 | 证据 |
|----|----------|-----------|----------|------|
| AC-1.1 | R-1 | TASK-CLI-001 | 集成 + 单测 | `cli_tool_framework/test/unittest/process_manager_test/` |
| AC-1.2 | R-2 | TASK-CLI-002 | 集成 | `cli_tool_framework/test/` |
| AC-1.3 | R-3 | TASK-CLI-002 | 集成 | `cli_tool_framework/test/` |
| AC-1.4 | R-4 | TASK-CLI-003 | 集成 | `cli_tool_framework/test/` |
| AC-1.5 | R-5 | TASK-CLI-004 | 单测 | `cli_tool_mgr_client_test/` |
| AC-1.6 | R-5 | TASK-CLI-004 | 单测 | `cli_tool_mgr_client_test/` |
| AC-1.7 | R-6 | TASK-CLI-005 | 单测 | `cli_tool_mgr_client_test/` |
| AC-1.8 | R-6 | TASK-CLI-005 | 单测 | `cli_tool_mgr_client_test/` |
| AC-1.9 | R-7 | TASK-CLI-005 | 单测 | `exec_tool_param_test/` |
| AC-1.10 | R-8 | TASK-CLI-005 | 单测 | `exec_options_test/` |
| AC-1.11 | R-8 | TASK-CLI-005 | 单测 | `exec_options_test/` |
| AC-1.12 | R-9 | TASK-CLI-006 | 单测 | `js_cli_manager` NAPI 单测 |
| AC-1.13 | R-10 | TASK-CLI-007 | 集成 | `cli_tool_framework/test/` |
| AC-1.14 | R-11 | TASK-CLI-004 | 集成 | `cli_tool_framework/test/` |
| AC-1.15 | R-12 | TASK-CLI-008 | 集成 | `cli_tool_mgr_client_test/` |
## 规则定义
| 规则ID | 类型 | 触发条件 | 预期行为 | 边界/约束 | 关联AC |
|--------|------|----------|----------|-----------|--------|
| R-1 | 行为 | 系统应用 + 持 EXEC_CLI_TOOL + toolName 已注册 + subcommand 合法 + args 匹配 inputSchema + challenge 非空 + options 合法 | 创建会话与受沙箱子进程执行工具,结束后 resolve `CliSessionInfo{status="completed", result.exitCode=进程退出码, outputText, errorText, executionTime}` | 退出码为 int32executionTime 为 int64 毫秒 | AC-1.1 |
| R-2 | 行为 | foreground(yieldMs>0) 模式 | 会话在 `yieldMs` 毫秒处派发 replyresolve 为 `status="running"` 的会话;会话切后台继续运行;后续结束通过会话事件(订阅)派发 | yieldMs 单位毫秒,int64 | AC-1.2 |
| R-3 | 行为 | background=true 模式 | 立即 resolve 为 `status="running"` 的会话;不调度 yield 任务;结束时向订阅者派发退出事件 | — | AC-1.3 |
| R-4 | 边界 | 进程运行时间 = options.timeout 秒(timeout>0 | 终止进程、`result.timeout=true`、向订阅者派发 "session timed out" 错误事件;若此前未后台则派发终态 reply | timeout 单位秒,上限 1800(=30 分钟);=0 表示不启用超时 | AC-1.4 |
| R-5 | 异常 | 调用方 Token 非系统应用,或未持 EXEC_CLI_TOOL 权限 | reject:非系统应用→35700008;缺权限→35700007 | 校验在入口执行 | AC-1.5, AC-1.6 |
| R-6 | 异常 | toolName 未注册;或 subcommand 非空但工具无子命令/不在子命令表 | reject 35700005ERR_TOOL_NOT_EXIST | subcommand 为空串时使用工具顶层 inputSchema | AC-1.7, AC-1.8 |
| R-7 | 异常 | args 含 inputSchema 未声明的键,或键值类型与 schema.type 不符 | reject 35700002ERR_INVALID_PARAM);特殊键 `help` 单独存在时放行 | args 为空对象视为合法 | AC-1.9 |
| R-8 | 边界 | options.timeout<0 或 >1800;或非后台且 yieldMs>timeout*1000;或 yieldMs<0 | reject 35700002ERR_INVALID_PARAM | timeout∈[0,1800] 秒;yieldMs∈[0, timeout*1000] 毫秒(非后台) | AC-1.10, AC-1.11 |
| R-9 | 边界 | 实参个数<4;或 toolName/challenge 为空串或非字符串;或 args 非对象 | 同步抛出 invalid parameter 异常(不进入异步 Promise) | NAPI 层校验先于服务端 | AC-1.12 |
| R-10 | 边界 | 调用时活动会话数 ≥ 系统并发上限 | reject 35700001ERR_SESSION_LIMIT_EXCEEDED | 上限由系统配置 CcmUtil.GetCliConcurrencyLimit 决定 | AC-1.13 |
| R-11 | 异常 | 调用方 Token 非 HAP(无法生成沙箱配置) | reject 35700003ERR_NOT_HAP | 沙箱配置生成失败前置 | AC-1.14 |
| R-12 | 恢复 | CliToolManager SA 未加载或代理为空 | reject 35700000GET_CLI_TOOL_MGR_SERVICE_FAILED | 客户端按需拉起 SA;拉起失败即此码 | AC-1.15 |
## 验证映射
| 编号 | 对应规格项 | 验证方式 | 验证重点 |
|------|------------|----------|----------|
| VM-1 | R-1 / AC-1.1 | 集成 + 单测 | 正常执行返回 completed 会话与退出码 |
| VM-2 | R-2,R-3 / AC-1.2,AC-1.3 | 集成 | yield/background 模式 reply 时机与 status |
| VM-3 | R-4 / AC-1.4 | 集成 | 超时终止、result.timeout、错误事件派发 |
| VM-4 | R-5 / AC-1.5,AC-1.6 | 单测 | 系统应用判定与权限校验路径 |
| VM-5 | R-6,R-7,R-8 / AC-1.7AC-1.11 | 单测 | 工具/子命令/schema/超时参数校验 |
| VM-6 | R-9 / AC-1.12 | 单测 | NAPI 参数校验同步抛错 |
| VM-7 | R-10,R-11,R-12 / AC-1.13AC-1.15 | 集成 + 单测 | 会话上限、非 HAP、SA 不可用 |
## API 变更分析
### 新增 API
| API 名称 | 开放范围 | 入参概要 | 返回值 | 错误码范围 | 功能描述 | 关联 AC |
|----------|----------|----------|--------|------------|----------|---------|
| `cliTool.execTool` | System | `(toolName: string, subcommand: string, args: object, challenge: string, options?: ExecOptions)` | `Promise<CliSessionInfo>` | 3570000035700008, 35700020 | 按名称执行已注册 CLI 工具,返回会话信息 | AC-1.11.15 |
> API 签名、d.ts 位置、权限要求等实现细节见 design.md。ExecOptions/CliSessionInfo/ExecResult 的字段语义见下「接口规格」。
### 变更/废弃 API
无变更或废弃项。
## 接口规格
### 接口定义
**execTool**
| 属性 | 值 |
|------|-----|
| 函数签名 | `execTool(toolName: string, subcommand: string, args: object, challenge: string, options?: ExecOptions): Promise<CliSessionInfo>` |
| 返回值 | `Promise<CliSessionInfo>` — resolve 为会话信息;reject 为错误码 |
| 开放范围 | System |
| 权限 | `ohos.permission.EXEC_CLI_TOOL`,且调用方须为系统应用 |
| 错误码 | 35700000, 35700001, 35700002, 35700003, 35700004, 35700005, 35700007, 35700008 |
| 关联 AC | AC-1.11.15 |
**参数约束**
| 参数 | 类型 | 必填 | 默认值 | 约束条件 |
|------|------|------|--------|---------|
| toolName | string | 是 | — | 非空;须为已注册工具名,否则 35700005 |
| subcommand | string | 是 | — | 可为空串(工具无子命令时);非空时须在工具子命令表内,否则 35700005 |
| args | objectWantParams 键值对) | 是 | — | 键须在工具 inputSchema.properties 内且类型匹配;空对象合法;特殊键 `help` 须单独存在 |
| challenge | string | 是 | — | 非空 |
| options | ExecOptions | 否 | `{background:false, yieldMs:0, timeout:0}` | 见 ExecOptions 约束 |
**ExecOptions 约束**
| 字段 | 类型 | 默认 | 约束 |
|------|------|------|------|
| background | boolean | false | true=后台立即返回;false=前台,可由 yieldMs 触发让出 |
| yieldMs | number(int64) | 0 | ≥0,单位毫秒;仅 foreground 生效;foreground 下须 ≤ timeout*1000 |
| timeout | number(int64) | 0 | ∈[0,1800],单位秒;0=不启用超时;timeoutMs=timeout*1000 |
**CliSessionInforesolve 值)**
| 字段 | 类型 | 说明 |
|------|------|------|
| sessionId | string | 会话唯一标识 |
| toolName | string | 工具名 |
| status | string | `"running"` / `"completed"` / `"failed"` |
| result | ExecResult \| undefined | 仅 completed/failed 时存在 |
**ExecResult**
| 字段 | 类型 | 说明 |
|------|------|------|
| exitCode | number(int32) | 子进程退出码,默认 1 |
| outputText | string | 标准输出累计 |
| errorText | string | 标准错误累计 |
| signalNumber | number(int32) | 终止信号,0 表示正常 |
| timeout | boolean | 是否因超时终止 |
| executionTime | number(int64) | 执行耗时(毫秒) |
**行为场景**
| # | 触发条件 | 预期行为 | 关联 AC |
|---|----------|----------|---------|
| 1 | 前台 + timeout=0 + yieldMs=0 + 进程正常退出 | 进程退出且输出排空后 resolve `status="completed"`,含 exitCode/outputText | AC-1.1 |
| 2 | 前台 + yieldMs>0 | yieldMs 毫秒处 resolve `status="running"`,会话转后台;后续结束经订阅事件通知 | AC-1.2 |
| 3 | background=true | 立即 resolve `status="running"`;结束时向订阅者派发退出事件,不再二次 resolve | AC-1.3 |
| 4 | timeout>0 且进程未在 timeout 秒内退出 | 终止进程、`result.timeout=true`、派发 "session timed out" 事件;未后台则派发终态 reply | AC-1.4 |
| 5 | 非系统应用调用 | reject 35700008 | AC-1.5 |
| 6 | 系统应用缺权限 | reject 35700007 | AC-1.6 |
| 7 | toolName 未注册 / subcommand 非法 | reject 35700005 | AC-1.7, AC-1.8 |
| 8 | args 不符 inputSchema | reject 35700002 | AC-1.9 |
| 9 | options.timeout/yieldMs 越界 | reject 35700002 | AC-1.10, AC-1.11 |
| 10 | 必填参数缺失/类型错/实参<4 | 同步抛 invalid parameter 异常 | AC-1.12 |
| 11 | 会话数达上限 | reject 35700001 | AC-1.13 |
| 12 | 非 HAP 调用 | reject 35700003 | AC-1.14 |
| 13 | SA 不可用 | reject 35700000 | AC-1.15 |
## 兼容性声明
- **已有 API 行为变更:** 否。本特性为新增 System API,不改变既有公共 API 行为。
- **配置文件格式变更:** 否(沙箱配置为内部生成,非对外配置文件)。
- **数据存储格式变更:** 否。会话为运行态内存对象,不持久化。
- **最低支持版本:** 参见 proposal.md(待基线)。
- **API 版本号策略:** 新增 API 自首个引入版本起标注 `@since`;错误码 357000xx 为本特性专属区间,不可被其他特性复用数值。
## 架构约束
| 关键约束 | 约束说明 | 影响 AC |
|----------|----------|---------|
| 仅系统应用 + `ohos.permission.EXEC_CLI_TOOL` 可调用 | 入口须做系统应用判定与权限校验 | AC-1.5, AC-1.6 |
| 执行须在受限沙箱子进程中进行 | 调用方须为 HAP 以生成沙箱配置 | AC-1.14 |
| 回复经 IPC Scheduler 异步派发 | 回调不在调用线程同步执行 | AC-1.1–1.4 |
| 并发会话受系统上限约束 | 超限拒绝,不排队 | AC-1.13 |
> 架构规则适用性及设计方案(SA 注册、IPC Stub/Proxy、沙箱生成、IOMonitor 调度等)见 design.md。
## 非功能性需求
| 类型 | 指标/阈值 | 验证方式 | 证据 |
|------|-----------|----------|------|
| 可靠性 | 单次 execTool 调用不应导致 CliToolManager SA 崩溃 | 压力测试 | `cli_tool_framework/test/` |
| 安全 | 非系统应用/无权限/非 HAP 调用均被拒绝 | 单测 | `cli_tool_mgr_client_test/` |
| 可测试性 | execTool 行为可经 mock 服务端校验错误码与回复时机 | 单测 | `cli_tool_mgr_client_test/``exec_options_test/` |
| 定界定位 | 失败路径经 HiSysEvent 上报(bundleName、toolName、failureReason/duration | hisysevent | `hisysevent.yaml` |
## 多设备适配声明
| 设备类型 | 行为差异 | 规格/约束 | 验证方式 | 证据 |
|----------|----------|-----------|----------|------|
| 手机 | 无差异 | — | 集成 | `cli_tool_framework/test/` |
| 平板 | 无差异 | — | 集成 | `cli_tool_framework/test/` |
| 折叠屏 | 无差异 | — | 集成 | `cli_tool_framework/test/` |
> execTool 行为与设备形态无关;并发上限等可随产品配置调整,不影响行为语义。
## 全局特性影响
| 特性 | 适用? | 结论 | 关联场景 |
|------|--------|------|----------|
| 无障碍 | 否 | execTool 为无界面 System API | — |
| 大字体 | N/A | — | — |
| 深色模式 | N/A | — | — |
| 多窗口/分屏 | 否 | 与窗口无关 | — |
| 多用户 | 否 | 权限与沙箱按调用方 Token 校验,不依赖用户切换 | — |
| 版本升级 | 否 | 无持久化数据需迁移 | — |
| 生态兼容 | 否 | 仅系统应用可用 | — |
## Spec 自审清单
在提交审查前逐项自检:
- [x] 无"待定""TBD""TODO"等占位符("待基线"为上游 proposal 缺失的如实标注,非规格占位)
- [x] 所有 AC 使用 WHEN/THEN 格式,可独立测试
- [x] 范围边界明确(仅 execToolexecCmd 等不涉及)
- [x] 无语义模糊表述
- [x] AC 与规则表交叉一致(每个 AC 至少关联一条规则,每条规则至少关联一个 AC)
- [x] 规则表每条通过 5 项质量检查(可复现/可观测/边界值/关联AC/无冲突)
## context-references
```yaml
context-queries:
- repo: "openharmony/ability_runtime"
query: "cli_tool_framework execTool 的 SA 注册、IPC Stub/Proxy 序列化与沙箱生成实现"
- repo: "openharmony/ability_runtime"
query: "ExecToolParam/ExecOptions/CliSessionInfo 的 Parcelable 编解码分支"
```
**关键文档:**
- `cli_tool_framework/frameworks/js/napi/cli_tool_manager/src/js_cli_manager.cpp`NAPI 入口 `execTool`/`OnExecTool`
- `cli_tool_framework/services/climgr/src/cli_tool_manager_service.cpp`(服务端 `ExecTool`、超时/让出处理)
- `cli_tool_framework/services/climgr/src/tool_util.cpp`(参数与 inputSchema 校验)
- `cli_tool_framework/interfaces/cli_tool/include/cli_error_code.h`(错误码定义)
- `cli_tool_framework/interfaces/cli_tool/ICliToolManager.idl`IPC 接口)