---
docStatus: current
---

# 独立事项包开发

读取、创建、完整更新和发布工作区独立事项包，以精确成员版本供 Workflow human 节点引用。

事项包由 `issue-definition` Owner 独立管理，归属于工作区，**不属于 Bundle，不进入 Bundle Manifest，也不通过 Bundle 安装或升级发布**。
一个事项包文档包含多个具名事项定义；Workflow 的 human 节点引用已发布包的精确成员版本。

事项包身份是 `environmentKey + packageId`，`packageKey` 是工作区内的作者键。草稿修订号 `revision` 与不可变 `semanticVersion` 分开管理。
更新草稿不会改变已发布版本，事项包发布也不会自动更新 Workflow 引用。

## 1. 确认 CLI 和授权

```bash
baijimu --version
baijimu workspace issue-definition --help
baijimu workspace issue-definition update --help
baijimu workspace issue-definition publish --help
baijimu auth status --verify
```

命令参数以目标机器分级帮助为准。没有 `workspace issue-definition` 表示该 CLI 尚未提供此作者入口；
不能用 `bundle resource object`、通用 Bundle 作者命令或 Runtime 查询接口替代。
所有操作显式提供工作区。Owner 校验当前用户、工作区权限、来源所有权及草稿修订，不以安装基础套件作为作者授权。

## 2. 编写完整事项包 document

将下例保存为 `issue-definition.json`。输入、输出和状态采用 [Type14 类型系统](/development/type-system/)；
审核结果字段属于业务合同，平台不预置 accepted、approved 或 decision。

```json
{
  "schemaVersion": "1.0.0",
  "typeProtocol": "14.0.0",
  "issues": {
    "business.review": {
      "name": "业务审核",
      "description": "核对业务摘要并提交审核结果",
      "tags": [
        "review"
      ],
      "inputType": {
        "@type": "JsonSchema",
        "schema": {
          "type": "object",
          "properties": {
            "summary": {
              "type": "string"
            }
          },
          "required": [
            "summary"
          ],
          "additionalProperties": false
        }
      },
      "outputType": {
        "@type": "JsonSchema",
        "schema": {
          "type": "object",
          "properties": {
            "accepted": {
              "type": "boolean"
            },
            "comment": {
              "type": "string"
            }
          },
          "required": [
            "accepted",
            "comment"
          ],
          "additionalProperties": false
        }
      },
      "processActions": [
        "manual_process"
      ],
      "statusType": null
    }
  }
}
```

- 文档顶层声明 `schemaVersion: "1.0.0"`、`typeProtocol: "14.0.0"` 和非空 `issues` 对象。每个成员使用显式 key；例子的 `business.review` 与 human 引用中的成员名一致。
- `name` 必填，最多 200 个字符；`description` 可省略，填写时最多 4000 个字符；文本不得为空或有首尾空白。
- 每个成员声明 `tags` 和 `processActions` 数组，无内容时填写 `[]`；每项最多 100 个字符。处理动作不能代替输出字段定义。
- `inputType`、`outputType` 和可选的 `statusType` 使用同一平台 Type 合同。用于工作流 human 的定义必须声明 `outputType`。
- 成员定义不包含 `enabled`、分配或执行策略。正式引用使用 Owner 返回的精确包版本和成员 key；分配与执行策略由 human 节点配置。
- 事项包 key 在创建时通过 `--package-key` 指定，不放进 document；来源环境、packageId、修订号和版本由 Owner 管理。
- 不使用旧的 `inputSchema/outputSchema/statusSchema` 字段；完整 Type 位置填写 `{"@type":"JsonSchema","schema":...}`，标准 JSON Schema 正文放在 `schema` 中。

完整更新必须提交同一份包含 `schemaVersion`、`typeProtocol` 和 `issues` 的完整文档。历史草稿读取可能保留原有 `DataType` 或空类型；
应以业务源码编写完整的 Type14 定义并显式更新，再回读核对输入、输出及状态类型。
已有不可变版本不会随草稿更新而改变，不能通过读取时补字段或改写旧版本完成迁移。

## 3. 创建、读取、更新与发布

先查询当前工作区拥有的包，再对目标执行操作：

```bash
baijimu workspace issue-definition list --workspace-id <WORKSPACE_ID> --json

baijimu workspace issue-definition create --workspace-id <WORKSPACE_ID> \
  --package-key <PACKAGE_KEY> --document @issue-definition.json --json

baijimu workspace issue-definition get <PACKAGE_ID> --workspace-id <WORKSPACE_ID> \
  --environment-key <SOURCE_ENVIRONMENT_KEY> --json

baijimu workspace issue-definition update <PACKAGE_ID> --workspace-id <WORKSPACE_ID> \
  --environment-key <SOURCE_ENVIRONMENT_KEY> --expected-revision <READ_REVISION> \
  --document @issue-definition.json --json

baijimu workspace issue-definition publish <PACKAGE_ID> <ISSUE_VERSION> --workspace-id <WORKSPACE_ID> \
  --environment-key <SOURCE_ENVIRONMENT_KEY> --expected-revision <CURRENT_REVISION> --json

baijimu workspace issue-definition versions <PACKAGE_ID> --workspace-id <WORKSPACE_ID> \
  --environment-key <SOURCE_ENVIRONMENT_KEY> --json

baijimu workspace issue-definition version <PACKAGE_ID> <ISSUE_VERSION> --workspace-id <WORKSPACE_ID> \
  --environment-key <SOURCE_ENVIRONMENT_KEY> --json
```

使用 create/get 返回的 `package.environmentKey`、`package.packageId` 和 `revision`，不使用 Bundle ID、资源 key 或名称代替身份。
完整更新使用读取时的 revision；更新成功后使用返回的新 revision 发布。修订冲突时回读并核对差异，不能自动刷新修订号重试覆盖。
发布严格 SemVer 的不可变版本，不能覆盖已有版本。分别评估事项包、Workflow 和 Bundle 自身版本，不把它们当作同一发布单元。

list 使用 `--page-size` 和 `--cursor` 分页，cursor 是 Owner 返回的 `nextCursor` JSON，也可保存为文件后使用 `--cursor @cursor.json`。
versions 的 `--cursor` 是 Owner 返回的精确版本字符串；CLI 不自动遍历或猜测下一页。
version 返回精确包版本的 JSON 制品，包含 `version` 和 `document`，不是安装台账。

人工作业引用形式是 `baijimu-issue://<environmentKey>/<packageId>@<semanticVersion>#<memberKey>`。
身份、版本和成员必须来自真实 Owner 目录或发布结果，示例身份不能直接套用。跨工作区消费还需按 Owner 当前共享及精确版本使用权合同授权，知道 URI 不等于获得访问权。

### 正式 Owner API

公开 Partner 前缀为 `/partner/v1/issue-definition/api/issue-definition-packages`，通过当前环境平台入口，使用 CLI 当前已授权的工作区凭据调用；不填写内部服务地址。

| 操作      | 方法和相对路径                                                                                 | 请求                                                                       |
| ------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| 工作区拥有目录 | `POST /pages`                                                                           | `workspaceId`、`catalog: "owned"`、`pageSize`、`cursor`                     |
| 创建      | `POST /`（前缀本身，无尾斜杠）                                                                     | `workspaceId`、`packageKey`、`document`                                    |
| 读取草稿    | `GET /{environmentKey}/{packageId}`                                                     | 无请求体                                                                     |
| 完整更新草稿  | `PUT /{environmentKey}/{packageId}/draft`                                               | `expectedRevision`、`document`                                            |
| 发布版本    | `POST /{environmentKey}/{packageId}/versions`                                           | `expectedRevision`、`semanticVersion`                                     |
| 版本目录    | `POST /versions/pages`                                                                  | `workspaceId`、`package: {environmentKey, packageId}`、`pageSize`、`cursor` |
| 精确版本制品  | `GET /{environmentKey}/{packageId}/versions/{semanticVersion}/artifact?workspaceId=...` | 无请求体                                                                     |

`workspaceId` 是字符串；`expectedRevision` 是正整数。读取/写入/发布的成功及错误使用 CModel；artifact 成功直接返回 `application/json` 不可变制品，错误仍为 CModel。
例如更新正文为 `{"expectedRevision":3,"document":<完整事项包文档>}`，发布正文为 `{"expectedRevision":4,"semanticVersion":"<ISSUE_VERSION>"}`；这些片段说明请求结构，需替换为合法 JSON 和实际值。

## 4. 配置 human 节点与验证

下例与上面的输入输出合同配套。替换目录返回的事项定义身份、版本和候选用户后，将节点加入完整 Workflow：

```json
{
  "type": "human",
  "id": "review",
  "name": "人工审核",
  "input": {
    "summary": "{{input.summary}}"
  },
  "assignment": {
    "mode": "candidates",
    "candidates": [
      {
        "identityType": "user",
        "identityId": "{{input.reviewerUserId}}"
      }
    ]
  },
  "executionPolicy": {
    "completionTimeoutSecs": 86400
  },
  "issueDefinitionReference": "baijimu-issue://example-origin/00000000-0000-4000-8000-000000000001@1.0.0#business.review"
}
```

工作流输入需要声明 `summary` 和 `reviewerUserId`。`reviewerUserId` 必须来自当前工作区有效用户目录，
不能将用户姓名、设备 ID 或其他工作区用户 ID 当作候选用户。

- `input` 显式映射到事项的 `inputPayload`；不会隐式发送整个 Workflow 输入或上下文。
- `assignment.mode: "candidates"` 必须有非空候选列表。`identityType` 支持 `user / department / group / role`；角色候选的 `identityId` 对 Bundle 角色使用完整 `ROLE` Locator，对工作区角色保留该工作区的 `roleKey`；Bundle 角色匹配必须具有正确的 Runtime 上下文。旧工作流合同中的裸 Bundle `roleKey` 需显式迁移，不能按同名解析。参见[角色开发](/development/bundle-development/role-template-development/)。
- 明确用户列表校验、去重后，单人直接分配到 `Issue.assignee`，多人由其中一人领取。含角色、部门或群组时始终是候选范围；领取或转交后的唯一处理者是 `Issue.assignee`。
- 对工作区成员开放领取时显式使用 `assignment: {"mode":"workspace_members"}`，不能用空候选列表表达。
- 结果以节点 `id` 为身份，例子写入 `context.review`；输出类型始终归 IssueDefinition，Human 不配置 `result` 或节点级 `outputSchema`。
- `completionTimeoutSecs` 是人工等待期限，必须大于零；它不是 HTTP 请求超时，省略表示不配置期限。

人工完成时提交与 `outputType` 一致的结果，例如 `{"accepted":true,"comment":"核对通过"}`。
Issue 校验通过后，由平台回传结果并推进 human 节点；下游据 `context.review.accepted` 判断业务分支。
`accepted:false` 仍是合法业务结果，不自动等于 Workflow 执行失败。

### 从前置节点读取候选人

前置节点若使用 `id: "ownerLookup"`，其结果写入 `context.ownerLookup`。
例如实际输出为以下对象，`reviewerUserId` 的值必须是当前工作区有效用户目录中的真实 ID：

```json
{
  "summary": "待审核的报告摘要",
  "reviewerUserId": "<VALID_WORKSPACE_USER_ID>"
}
```

把上面完整 human 节点中的 `input` 和 `assignment` 替换为以下片段，保留原有的
`issueDefinitionReference` 和执行策略。连线必须让前置节点先完成，再执行 human：

```json
{
  "input": {
    "summary": "{{context.ownerLookup.summary}}"
  },
  "assignment": {
    "mode": "candidates",
    "candidates": [
      {
        "identityType": "user",
        "identityId": "{{context.ownerLookup.reviewerUserId}}"
      }
    ]
  }
}
```

路径必须按实际节点输出合同填写；若返回值还有外层 `data`，应引用真实的嵌套路径，不能只凭节点 ID
猜输出位置。`identityId` 引用的是一个主体 ID，不是用户对象、用户姓名或数组。运行时解析为空或用户身份无效会报错，不会自动开放给全工作区；相同类型与 ID 的重复候选主体会去重。

### 动态用户列表：单人分配，多人领取

需要使用前置节点返回的任意长度用户列表时，继续使用 `assignment.mode: "candidates"`，将整组引用直接放在 `candidates`。
前置节点应返回真实的当前工作区用户 ID **字符串数组**，例如：

```json
{
  "summary": "待审核的报告摘要",
  "userIds": ["<VALID_WORKSPACE_USER_ID>", "<ANOTHER_VALID_WORKSPACE_USER_ID>"]
}
```

假设该节点的 `id` 是 `ownerLookup`，完整 human 节点可以写成：

```json
{
  "id": "reviewReport",
  "type": "human",
  "name": "审核报告",
  "input": {
    "summary": "{{context.ownerLookup.summary}}"
  },
  "assignment": {
    "mode": "candidates",
    "candidates": "{{context.ownerLookup.userIds}}"
  },
  "issueDefinitionReference": "baijimu-issue://example-origin/00000000-0000-4000-8000-000000000001@1.0.0#business.review"
}
```

替换示例中的身份占位符；事项定义的 `inputType` / `outputType` 与本页定义保持一致。
Workflow 保存的是运行时数据引用，实际员工来自执行时所在工作区的用户目录。
若名单由 Event Trigger 传入 Workflow，改用 `"candidates": "{{input.userIds}}"`，并在 Workflow `inputSchema`
声明对应的字符串数组。也可直接提供真实用户 ID 的非空 JSON 字符串数组；跨工作区复用的 Bundle 应使用引用。

平台使用固定规则，无需配置“直接分配”或“领取”策略：

| 校验并去重后的名单             | 行为                                        |
| --------------------- | ----------------------------------------- |
| 1 人                   | 创建 Issue 时直接设置 `Issue.assignee`，该用户无需先领取。 |
| 多人                    | 创建一个候选池；其中一人领取后成为唯一处理者，其他候选人不能再领取。        |
| 空名单、缺失路径、`null` 或错误类型 | human 执行失败，不创建开放事项。                       |
| 任一用户不属于当前工作区          | 整组失败；不会丢弃无效用户后继续分配。                       |

字符串 ID 去掉首尾空白后必须是标准正整数格式；重复 ID 只保留一份。`["7","7"]` 的有效人数为 1，
适用单人自动分配。数值数组、用户对象数组、姓名数组和 JSON 字符串化数组均不接受；前置节点需要先输出
字符串 ID 数组。这里的数值仅说明格式，实际配置必须使用目录返回的身份。

`candidates` 整组引用必须完整指向 `input` 或 `context` 中的数组；不支持拼接、隐式取第一人或在此处执行 `=CEL`。
多候选不代表会签，也不会创建多份事项。human 重试复用原 Issue，不覆盖已领取或转派后的负责人。

### 一个候选入口，统一分配规则

`assignment.candidates` 接受三种形式：

| 形式          | 示例                                                  | 用途                                                               |
| ----------- | --------------------------------------------------- | ---------------------------------------------------------------- |
| 用户 ID 字符串数组 | `["7", "8"]`                                        | 已知的当前工作区用户列表。                                                    |
| 完整数组引用      | `"{{context.ownerLookup.userIds}}"`                 | 读取前置节点返回的用户 ID 字符串数组，也可引用 `input`。                               |
| 候选主体对象数组    | `[{"identityType":"role","identityId":"reviewer"}]` | 指定 `user / department / group / role` 主体；每项 `identityId` 可引用单个值。 |

前两种形式解析为 `user` 候选主体，与直接填写用户主体对象使用相同的校验、去重和分配规则。
示例数字只说明格式，必须替换为目录返回的真实用户身份。字符串数组与主体对象不能混在同一个数组中。
整组引用的结果必须是用户 ID 字符串数组，不能是用户对象数组或候选主体对象数组。

纯用户候选去重后只有一人时直接分配；多人时由其中一人领取。如果包含角色、部门或群组，保留候选范围，
即使只配置一个角色，也不会将其当成一个用户直接分配。混合用户与角色的主体对象数组同样需要领取，
其中显式用户仍必须通过工作区成员校验。`workspace_members` 继续表示显式开放工作区领取。

不再使用独立的 `mode: "users"` / `assignment.userIds`；也不添加 `mode: "direct"`、分配策略开关或节点级
`assignee`。不要把用户数组放进某一项 `identityId`，该字段仍只表示一个主体 ID。

### 从旧配置升级

旧 `users` 配置应把 `mode` 改为 `candidates`，将 `assignment.userIds` 的原值移到
`assignment.candidates`，然后创建新的 Workflow 版本。该收敛合同拒绝旧 `users` 模式，平台升级前需核对
不可变资源版本、运行时投影和执行快照；不可变版本不能原地改写。

原有纯用户 `candidates` 也使用上述人数规则：新建事项的单一用户无需领取。已经创建的 Issue 不会因此
重新分配，重试继续保留现有负责人和领取状态。需要维持旧行为的在途流程应按旧合同完成后再切换，
不能只更新文档或平台镜像而跳过存量检查。

事件绑定、输入映射和两种表达式语法见 [Event Trigger 教程](/development/bundle-development/event-trigger-development/)。
不要用公开 `wait.signal` 接口绕过人工事项处理。

Workflow 按[工作流开发](/features/workflows/)创建、更新并创建精确不可变版本。当前 human 使用上述
`issueDefinitionReference/input/assignment` 字段；历史 Workflow Schema 5.0.0 的 human 示例
采用旧字段，不能用它校验或生成本页的新节点。历史合同保持原样，遇到 CLI 字段不兼容时应先核对版本，不能混用两套合同。

## 5. 交付与验收

事项包发布完成后，让 Workflow human 引用该包的精确版本和成员 key。Workflow 仍按自身所属 Bundle 的交付规则创建版本并安装，
**Bundle 清单仅纳入 Workflow，不纳入事项包**。发布事项包本身无需创建 Bundle 版本或安装。

1. 回读草稿和精确版本制品，核对输入、输出、状态类型及发布版本。
2. 在实际消费工作区校验精确成员可访问；共享和版本使用权失败保持真实错误，不回退旧 Bundle 台账。
3. 启动 Workflow，核对 human 输入、单人直接分配、多候选领取、空/无效名单拒绝。
4. 提交符合 outputType 的结果，核对下游 context；另以缺失必填字段或错误类型确认校验生效。
5. 根据业务需要验证拒绝分支及人工等待超时。事项包发布成功不能替代业务链路验收。

## 公共 Rust 合同包

公开 [baijimu-issue-definition-contract](https://crates.io/crates/baijimu-issue-definition-contract) 提供精确事项包身份与成员引用；需要文档类型时启用 `document` feature。
合同类型不授予访问权，HTTP 用户凭据、工作区授权和实际执行由 Owner 校验。
