# 定义本体

本体（Ontology）是 Semantic 的语义层。它由 Object Type、属性、链接、Action 和函数组成，每个构件用一条 JSON 定义。这一页讲定义怎么写、怎么发布，以及智能体怎么在分支上改本体。

> [!NOTE]
> 前提：你是组织（命名空间 `cell-demo`）的 developer。定义与发布要 developer 角色。智能体只能在分支上改，开提案。在 review 策略下，由人审核提案。

## 本体由什么组成

本体有两类构件。名词描述数据，动词改数据并做计算。

### 名词：描述数据

| 构件 | 是什么 | 示例 |
| --- | --- | --- |
| **Object Type** | 一类对象：主键、标题、属性 | `customer` 客户公司、`agent` 智能体、`application` 应用、`modelUsage` 模型用量、`cloudCost` 云费用 |
| **Property** | 属性。类型取基础类型，如 string、integer、double、decimal、date、timestamp、array、struct、geopoint、vector、timeseries | `customer.location`（geopoint）、`customer.contact`（struct）、`modelUsage.dailyTokens`（timeseries） |
| **Derived Property** | 沿链接读时计算，最多 3 跳。聚合有 count、sum、avg、min、max、collectList、collectSet 等 | `customer.agentCount` 智能体数、`customer.modelCostUsd` 模型费用合计 |
| **Link Type** | 两个 Object Type 的关系，两端各有名字。一对多用外键，多对多另存每一条链接 | `customerAgents`：`customer.agents` 与 `agent.customer`；`applicationAgents`（多对多） |
| **Interface** | 多个 Object Type 共有的形状，可以继承 | `Billable`（继承 `Monthly`）：`modelUsage` 和 `cloudCost` 都实现它 |
| **Shared Property** | 跨类型复用的属性定义 | `costUsd`、`month` |
| **Value Type** | 带约束的类型，写入时校验：枚举、范围、长度、正则 | `cellId`（`cell-` 开头）、`yearMonth`（YYYY-MM）、`customerStage`（试点、付费、暂停、内部） |

### 动词：改数据与做计算

| 构件 | 是什么 | 示例 |
| --- | --- | --- |
| **Action Type** | 受控的写操作：参数、规则、提交条件 | `adjust-seats`：座位数不能少于成员数 |
| **Action Log** | 开了 `actionLog` 的 Action，每次成功执行写一条记录 | 谁在什么时候把哪家公司的座位数改成多少 |
| **Object Set** | 对象的集合：过滤、并、交、差，沿链接走，派生属性 | 付费客户的全部智能体 |
| **Function** | 代码写的逻辑，在隔离的运行时里执行 | `countPaidCustomers`，见下文「函数」 |

示例本体用 Demo Company（`cell-demo`）的虚构数据。样板应用见 [样板应用](samples.md)。

## 定义文件怎么写

每个定义是一个 JSON 对象。`kind` 写构件类型，`apiName` 写名字。`kind` 取值有 `objectType`、`linkType`、`actionType`、`interfaceType`、`sharedPropertyType`、`valueType`。

下面是示例本体里 `customer` 的一部分。

```json
{
  "kind": "objectType",
  "apiName": "customer",
  "title": "客户公司",
  "schema": {
    "titleColumn": "name",
    "columns": [
      { "name": "customerId", "type": "string", "primaryKey": true, "title": "公司 ID", "valueType": "cellId" },
      { "name": "name", "type": "string", "title": "名称", "notNull": true },
      { "name": "stage", "type": "string", "title": "阶段", "valueType": "customerStage" },
      { "name": "seats", "type": "integer", "title": "座位数", "unit": "个" },
      { "name": "agentCount", "type": "integer", "title": "智能体数",
        "derived": { "linkPath": ["agents"], "aggregation": { "type": "count" } } }
    ]
  }
}
```

链接 `customerAgents` 把公司和智能体连起来。一家公司有多个智能体，每个智能体属于一家公司。

```json
{
  "kind": "linkType",
  "apiName": "customerAgents",
  "title": "公司的智能体",
  "schema": {
    "from": "customer",
    "to": "agent",
    "cardinality": "ONE_TO_MANY",
    "apiNameAtoB": "agents",
    "apiNameBtoA": "customer",
    "foreignKey": { "side": "to", "property": "customerId" }
  }
}
```

Action `adjust-seats` 改一家公司的座位数。`submissionCriteria` 是提交条件：条件不成立，Action 不执行。

```json
{
  "kind": "actionType",
  "apiName": "adjust-seats",
  "title": "调整座位数",
  "schema": {
    "parameters": [
      { "name": "customer", "type": "object", "objectType": "customer", "title": "公司", "required": true },
      { "name": "seats", "type": "integer", "title": "新座位数", "required": true, "min": 1, "max": 10000 },
      { "name": "reason", "type": "string", "title": "理由", "maxLength": 200 }
    ],
    "rules": [
      { "type": "modifyObject", "objectType": "customer", "object": "$customer", "values": { "seats": "$seats" } }
    ],
    "submissionCriteria": [
      {
        "condition": {
          "type": "comparison",
          "left": { "param": "seats" },
          "operator": "gte",
          "right": { "param": "customer", "property": "members" }
        },
        "failureMessage": "座位数不能少于成员数"
      }
    ],
    "summary": "{customer} 座位数改为 {seats}",
    "actionLog": true
  }
}
```

名字的写法：

- Object Type 与 Interface 用 PascalCase：大写字母开头，只含字母和数字，例如 `Employee`。名字前可以带小写的命名空间前缀，例如 `production.OrderLine`。
- Object Type 名在本体里不分大小写，唯一。`ontology`、`object`、`link` 这类保留字不能用。
- 新的 Object Type 名不是 PascalCase 时，平台拒绝定义，返回 422 `invalid_schema`。分支检查的 `api_names` 一项是 FAIL。
- 属性、Value Type、Shared Property 用 camelCase，例如 `customerId`。
- Link Type 两端的名字用小写字母开头，只含字母和数字，例如 `agents`。
- Action Type 用 kebab-case，例如 `adjust-seats`。
- 示例本体的 `customer` 是早先建的小写开头的名字。已经存在的这类名字照常能用，定义时给出警告。

其他规则：

- 一个 Object Type 恰好有一个主键属性。
- 定义含未知字段时，平台拒绝定义，并在错误信息中给出字段路径。例如把 `submissionCriteria` 写成 `submissionCriterias`。
- `writeback: true` 的属性只在语义层维护，不接数据源。派生属性也不接数据源。
- Object Type 的 `datasources` 把数据流接到类型上。写法与规则见 [数据接入](connect.md)。

### 对象的编辑方式

新建的 Object Type 缺省只能经 Action 改。定义里的 `editsConfiguration.onlyAllowPrivilegedEdits` 缺省是 `true`。

- 直接写对象时，平台返回 403。直接写包括 `POST`、`PATCH`、`DELETE …/objects` 和 `import --layer edits`。错误里列出能改它的 Action。
- 要开放直接编辑，在定义里写 `"editsConfiguration": { "onlyAllowPrivilegedEdits": false }`。
- 重新定义时没写 `editsConfiguration`，平台沿用现有的设置。
- 数据源写入不受这项限制，例如同步和 `import --layer source`。

```json
{ "kind": "objectType", "apiName": "Inspection", "title": "检验记录",
  "editsConfiguration": { "onlyAllowPrivilegedEdits": false },
  "schema": { … } }
```

## 写定义并发布

用 CLI 整批提交定义，再发布一个语义版本。

```bash
aidc semantic define ontology/ --dry-run      # 整批检查：引用是否闭合，有哪些破坏性变更
aidc semantic define ontology/                # 整批提交：有则改，无则建
aidc semantic publish --notes "加了异常登记"    # 发布一个语义版本 vN
aidc semantic releases                        # 列出语义版本
```

- `define` 读目录里的全部 `.json` 文件，按文件名排序，整批一起校验。写入顺序是枚举与 Value Type → Shared Property → Interface → Object Type → Link Type → Action。
- 引用必须闭合。Action 改的属性、引用的参数、外键目标、枚举都要存在，否则定义被拒，返回 422。同一批里互相引用算数。
- `define --dry-run` 只检查。它报告引用是否闭合，以及相对上一个语义版本的破坏性变更。
- 不再用的定义，用 `aidc semantic archive <apiName>` 归档。
- `publish` 发布一个语义版本 vN，版本号只增。定义没变时，命令返回当前版本，不占新号。

## 版本与破坏性变更

语义版本是组织本体的版本号。应用日志里同时记语义版本和应用版本。

- 破坏性变更包括：删 Object Type、删属性、改类型、改主键，Action 删参数，或 Action 新增必填参数。
- 定义时返回破坏性变更。发布时记档，版本的 `changeKind` 为 `breaking`。发布前，确认调用它的应用都已经改好。
- 自进化采纳的语义改进会自动发新版本。见 [自进化 SDK](evolve.md)。

## 状态与删除

每个 Object Type、属性、Link Type、Action Type 和 Interface 都有一个状态。状态决定能不能删除。

| 状态 | 含义 |
| --- | --- |
| `active` | 缺省。应用在用 |
| `experimental` | 还在开发 |
| `deprecated` | 准备删除 |
| `example` | 安装的示例，只用于培训 |

删除一个 `active` 的构件要分两步：

1. 把状态改成 `deprecated` 或 `experimental`，定义或合并这次改动。
2. 再删除（归档）它。

改成 `deprecated` 时，写原因和预期删除时间。可以写替代它的构件。

```json
{ "kind": "objectType", "apiName": "ProductProfile", "title": "产品档案（旧）", "status": "deprecated",
  "deprecated": { "message": "并回 Product 的 edit-only 属性", "deadline": "2026-12-31", "replacedBy": "Product" },
  "schema": { … } }
```

- 新建时写的 `status` 立即生效，例如 `experimental`。
- 属性的 `status` 没写时，跟所属的类型一样。
- 要从定义里去掉一个 `active` 的属性，先把它写成 `"status": "DEPRECATED"`，并写属性自己的 `"deprecated": { "message": …, "deadline": … }`。`replacedBy` 写同一类型里替代它的属性。
- 一个提案可以同时删除一个属性和引用它的 Action，前提是两者都已是 `deprecated`。平台按合并之后的本体做检查，删除的 Action 不算引用。

## 分支与提案

智能体不能直接改 main 上的本体。它在分支上改、开提案。在 review 策略下，由人审核后合并。

```bash
export AIDC_AGENT_ID=ops-agent
aidc semantic branch create add-department
aidc semantic branch modify add-department ./ontology --dry-run
aidc semantic branch modify add-department ./ontology
aidc semantic objects agent --branch add-department
aidc semantic branch propose add-department --title "加部门对象类型" --trigger "问「采购部有几个智能体」答不出" --self-test "分支上能答：3 个"
```

- `branch create` 开分支。基线是当前语义版本。
- `branch modify` 把一整份定义放到分支上。`--dry-run` 只试跑。`--expected-version` 防止并发覆盖。
- `objects … --branch` 在分支上读对象，验证问题能答了。读接口都收 `--branch`。
- `branch validate` 看合并检查。
- `branch conflicts` 看和 main 冲突的地方。
- `branch rebase` 跟上 main。
- `branch propose` 开提案。`--trigger` 写为什么要改，`--self-test` 写自测结果。命令的输出里有审核地址，交给人打开。
- 平台给提案附上按资源的改动、校验结果、影响面（30 天的写入与活跃用户、依赖的应用）和破坏性改动。

作者由凭证决定。`AIDC_AGENT_ID` 存在时，CLI 带上 `x-aidc-author: agent:<id>`，作者记为智能体。用 Agent Key 调用时，作者一律记为智能体。

- 智能体直接定义 main，返回 409，错误码 `branch_required`。
- 智能体不能直接新建、修改、删除、导入数据，返回 403。改数据用 Action。

在 review 策略下，由人审核提案，逐项批准。破坏性改动要确认：CLI 加 `--confirm-breaking`，网页上输入实体名。全部批准、检查通过后，提案合并到 main，并发一个语义版本。

```bash
aidc semantic proposals --status OPEN
aidc semantic proposal <id>
aidc semantic proposal approve <id> --confirm-breaking
aidc semantic proposal merge <id>
```

## 审批策略：review 与 yolo

每个组织有一个审批策略。它决定谁能批准、合并提案，以及谁能发布智能体写的应用版本。

|  | review（缺省） | yolo |
| --- | --- | --- |
| 谁能批准、合并 | 本组织 developer 的网页登录 | 网页登录，加上能改这个本体的 Key：开发者 Key（含智能体在用的），或 Agent Key 代表的主体在本体上是 Editor 或 Owner |
| 作者自己的批准 | 不算数 | 作者能改这个本体，就算数 |
| 检查通过后 | 等人点「合并」 | 自动合并 |
| 发布智能体写的应用版本 | 人在网页上点「发布」 | 开发者 Key 也能发布 |

两种策略下都不变：

- 安全策略的改动，要满足相关 Marking 的人批准。
- 合并检查不过，不能合并。任何一项被驳回，也不能合并。
- 每次批准、驳回、合并、发布和改策略，都记进审计日志。
- 只读（Viewer）的智能体照样能开提案。批准要交给能改这个本体的审核人。
- 改回 review 时，智能体给的批准作废，回到待审核。

```terminal title="看审批策略"
$ aidc semantic approval-policy
cell-demo 审批策略 review：审核人 = 网页会话；需要 1 个批准；作者自己批准不算数；合并要审核人来点
```

改策略只给本组织的 developer 本人。智能体不能改。`aidc semantic approval-policy set review|yolo --dry-run` 只显示会变什么。

## Action：规则与提交条件

Action 是受控的写操作。它校验参数，检查提交条件，然后按规则改对象或链接。

- 参数有类型、必填、最小值、最大值、最大长度。对象参数指向一个 Object Type。
- 规则（`rules`）有六种：`createObject`、`modifyObject`、`createOrModifyObject`、`deleteObject`、`createLink`、`deleteLink`。
- 提交条件（`submissionCriteria`）每条是一个条件。条件不成立时，返回 `failureMessage`。
- `actionLog: true` 时，每次成功执行都写一条 Action Log。
- `roles` 写谁能执行。不写时，developer、member 和 editor 都能执行。

提交条件里，比较的值可以引用参数。对象参数可以指定属性。比较值也可以使用常量或执行人信息。写法如下。

- 参数：`{ "param": … }`
- 对象参数的属性：`{ "param": …, "property": … }`
- 常量：`{ "literal": … }`
- 执行人：`{ "user": "id" | "name" | "role" | "authorKind" }`

`authorKind` 的值是 `human` 或 `agent`。

下面的条件表示只有人能执行。写肯定的条件，不写「不是 agent」。

```json
{
  "condition": {
    "type": "comparison",
    "left": { "user": "authorKind" },
    "operator": "is",
    "right": { "literal": "human" }
  },
  "failureMessage": "只有人能执行"
}
```

用了 `authorKind` 的 Action，暂时只能经 v1 接口、CLI 或 Semantic 界面执行。v2 接口（OSDK）会返回 403。

## 函数

函数是代码写的逻辑。它在隔离的运行时里执行。发布后，同一版本的签名与源码不能改。

```bash
aidc semantic functions publish count.js --api-name countPaidCustomers --version 1.0.0 --output '{"type":"integer"}'
aidc semantic functions list
```

- 源码是 ES module，默认导出 `(params, ctx) => 结果`。`ctx` 按调用人的权限读对象：

| `ctx` 的成员 | 做什么 |
| --- | --- |
| `ctx.loadObjects(objectSet, { pageSize, select })` | 读一个对象集。给 `pageSize` 只取第一页；不给取全部，超过 100,000 个报 `ObjectsExceededLimit` |
| `ctx.aggregate(objectSet, aggregation, groupBy)` | 聚合，写法同 [聚合](data.md#聚合) |
| `ctx.getObject(objectType, primaryKey)` | 按主键取一个对象，没有时返回 `undefined` |
| `ctx.edits` | 编辑函数用：`createObject`、`modifyObject`、`deleteObject`、`addLink`、`removeLink`。编辑由调用它的 Action 统一提交 |
| `ctx.now` | 这次执行的时间 |

- 版本号照语义化版本写。同一版本、同一内容，返回「没有变化」。同一版本可以只更新超时或内存配置。此时返回「已更新配置」。同一版本、不同的签名或源码，报冲突。
- 智能体只能发预发布版本，例如 `1.1.0-rc.1`。
- 查询经 `/api/v2/ontologies/{命名空间}/queries/{函数}/execute` 执行。自动化的函数效果也执行它。见 [自动化](workflow.md)。

## Action 调外部系统

Action 可以调外部系统。webhook 挂在数据源上，凭证存在数据源里，调用方不接触凭证。

### writeback 与 side effect

- `writeback` 只有一个。它在校验通过后、规则执行前调用。外部系统拒绝或超时，整个 Action 不生效，语义层一条都不改。原因原样返回给执行人。webhook 返回 429 时，错误码是 `rate_limited`。其他执行失败时，错误码是 `webhook_failed`。
- `sideEffects` 最多 10 个。它们在改动提交后调用，顺序不保证。失败不回滚改动，也不报给执行人。结果记在这次执行的记录里。
- 输出在规则里用 `$writeback.<输出名>` 取。side effect 的输入也能用它。
- 输入的写法与规则相同：`$参数`、`$对象参数.属性`，或字面量。
- 只校验（`VALIDATE_ONLY`）与预演不调用外部系统。有 writeback 的 Action 不收批量提交（`applyBatch`）。

把 webhook 写进 Action 定义的 `schema` 里。下面是 `schema` 中的 `webhooks` 部分。`writeback` 的 `<数据源>/<名字>` 换成自己的 webhook。

```json
{
  "webhooks": {
    "writeback": { "webhook": "<数据源>/<名字>", "inputs": { "customerId": "$customer.customerId" } },
    "sideEffects": [{ "webhook": "im-robot/send-text", "inputs": { "content": "$message" } }]
  }
}
```

- 规则只写 `writeback: true` 的属性。状态这类从数据源来的属性，如果规则去写它，规则写入的值会一直盖住之后同步来的值。定义时会提醒。
- 定义时执行以下检查：
  - webhook 存在。
  - 必填输入都给了。
  - 没有多余的输入。
  - `$writeback.<输出>` 是 webhook 的输出。
  - 组织能用这个数据源。

### REST API 数据源上的 webhook

自己的系统先建一个 REST API 数据源，再在它上面建 webhook。数据源的建法见 [数据接入](connect.md)。下面是一个向企业 IM 群发文本的 webhook。

```json
{
  "connection": "im-robot",
  "apiName": "send-text",
  "displayName": "群里发一条文本",
  "inputs": { "content": { "type": "string" } },
  "calls": [{
    "method": "POST",
    "path": "/robot/send",
    "body": { "type": "json", "value": { "msgtype": "text", "text": { "content": "{{content}}" } } },
    "extract": { "errcode": "/errcode", "errmsg": "/errmsg" }
  }],
  "outputs": { "errcode": { "type": "integer" }, "errmsg": { "type": "string" } },
  "limits": { "timeoutMs": 10000, "rateLimit": { "executions": 20, "per": "minute" } }
}
```

- `inputs` 的类型有 `boolean`、`integer`、`long`、`double`、`string`、`date`、`timestamp`、`list`、`record`、`optional`。不是 `optional` 的都必填。
- `calls` 最多 10 个，按顺序执行。请求体可以是 `json`、`formUrlEncoded` 或 `text`。数据源的认证自动加上，请求里不再写。
- 最多一个请求会改外部系统，即方法不是 GET、HEAD、OPTIONS 的请求。换令牌这类不改数据的 POST，标 `"isHttpMethodSafe": true`。
- 模板：`{{名字}}` 原样插入文本，`{{json 名字}}` 插入 JSON。`{{secrets.<名字>}}` 取数据源的秘密，只在发送那一刻解开，预演和任何回显里都打码。
- `extract` 用 JSON pointer 从响应里取值，取出的变量给后面的请求用。
- 很多 IM 接口出错时仍返回 HTTP 200，把错误放在 `errcode` 里。把它配成输出，执行记录里就能看到。
- 上限：`timeoutMs` 缺省 20 秒，最多 180 秒。`rateLimit` 缺省每分钟 30 次。`concurrency` 缺省 10。`retryableStatusCodes` 遇到就重试，最多 2 次。
- 出口：平台从公网直连。解析到内网或本机地址的域名会被拒绝。
- 权限：webhook 的查看、建、改、删、手动试，只给本组织的 developer。经 Action 调用时，只看 Action 的权限。

```bash
aidc semantic connectivity webhook put --ontology cell-demo --file send-text.json --dry-run
aidc semantic connectivity webhook put --ontology cell-demo --file send-text.json
aidc semantic connectivity webhook test <webhookRid> --inputs '{"content":"测试"}' --dry-run
aidc semantic connectivity webhook test <webhookRid> --inputs '{"content":"测试"}'
```

`--dry-run` 只渲染请求，秘密打码，不发出。去掉 `--dry-run`，才真发一次。

### Action 执行后发邮件

Action 可以配 `notifications`。改动提交后，给每个收件人发一封邮件。派任务、转派、提交验收这类「要让某个人知道」的 Action 用它。

```json
{
  "kind": "actionType",
  "apiName": "create-dev-task",
  "title": "派任务",
  "schema": {
    "parameters": [{ "name": "title", "type": "string", "required": true }, { "name": "assignee", "type": "object", "objectType": "employee", "required": true }],
    "rules": [{ "type": "createObject", "objectType": "devTask", "values": { "taskId": "$uuid", "title": "$title", "assigneeId": "$assignee", "assigneeAccountId": "$assignee.accountId", "assignedAt": "$now", "status": "待接受" } }],
    "notifications": [{
      "recipients": "$assignee.accountId",
      "subject": "新任务：{{{title}}}",
      "body": "{{{actionTriggerer}}} 派给你一个任务：{{{title}}}",
      "link": { "text": "打开任务", "target": { "type": "newObject", "objectType": "devTask" } }
    }],
    "actionLog": true
  }
}
```

- 收件人可以是 `$参数`、`$对象参数.属性`（对象上存的 AIDC 账号 ID）、`$user`（执行人），或固定的账号 ID。可以写成数组。收件人必须是本组织的人。
- `subject` 最多 250 字，`body` 最多 1,000 字，超长截断。`{{{参数}}}` 插入参数值。内容按改动之前渲染。
- `link` 指向对象参数、这次新建的对象，或一个 URL。
- 缺省时，只要有一个收件人不合格，整个 Action 就不执行。`"notificationSettings": { "renderingSettings": "anyNotificationRenderingCanFail" }` 改为只发给合格的人。
- 预演返回会发给谁、标题和正文，不发。每封邮件记在外发账里。
- 逾期提醒用自动化的「对象集全部对象」条件。见 [自动化](workflow.md)。

## 和 ERP、OA 的关系

ERP、MES、OA 缺省只读。它们的数据经数据流同步进来。人和智能体的改动只走 Action，落在语义层。数据源下一次同步，不会冲掉这些改动。要改源系统本身，给 Action 配 writeback webhook。源系统先接受，语义层才记一笔。

## 限制

下表列出本体相关的上限。

| 项目 | 上限 |
| --- | --- |
| 一个 Object Type 的主键属性 | 恰好一个 |
| 一次 Action 改的对象 | 10,000 个 |
| 一次 Action 碰的 Object Type | 50 个 |
| `applyBatch` 一次的请求 | 20 个，一个事务 |
| 一个 Action 的 side effect | 10 个 |
| 一个 webhook 的请求（`calls`） | 10 个 |
| webhook 的超时（`timeoutMs`） | 缺省 20 秒，最多 180 秒 |
| 分支名 | 小写字母、数字、`.`、`_`、`-`，最多 63 个字符，必须以小写字母或数字开头 |
| 提案标题 | 160 个字符 |
| 提案的触发原因（`--trigger`） | 2,000 个字符 |
| 派生属性的链接跳数 | 最多 3 跳 |
| 一次分支修改的新增或更新实体 | 200 个 |
| 一次分支修改的归档实体 | 200 个 |

## 常见错误

下表列出定义、分支、提案和 webhook 的常见错误。

| 现象 | 原因 | 怎么办 |
| --- | --- | --- |
| 定义被拒，错误信息提到引用 | Action 改的属性、引用的参数、外键目标或枚举不存在 | 补上缺的定义。同一批里的互相引用算数 |
| 定义被拒，提示未知字段 | 字段名拼错，例如 `submissionCriterias` | 改成正确的字段名。错误信息给出路径 |
| 409，`branch_required` | 智能体直接改 main | 在分支上改，开提案 |
| 403，`forbidden`，智能体写数据 | 智能体不能直接新建、修改、删除、导入数据 | 改数据用 Action |
| 提案无法合并 | 有任务没批准，或合并检查没通过 | 用 `aidc semantic proposal <id>` 看检查结果 |
| `branch_conflict` | 分支与 main 有冲突 | 用 `aidc semantic branch conflicts <分支名>` 看，再 `aidc semantic branch rebase <分支名>` |
| `webhook_failed` | writeback 的外部系统拒绝或超时 | 看返回的原因。语义层没有改动，修好外部系统后重试 |
| 破坏性改动要确认 | 删属性、改类型、改主键，或 Action 新增必填参数 | 确认调用它的应用都已改好，批准时加 `--confirm-breaking` |
| 422，`invalid_schema`，提到名字 | 新的 Object Type 名不是 PascalCase | 改成大写字母开头，例如 `OrderLine` |
| 删除被拒，提到状态 | 构件还是 `active` | 先改成 `deprecated` 或 `experimental`，再删 |
| 403，错误里列出 Action | 类型只允许经 Action 改 | 用列出的 Action 改。或在定义里开放直接编辑 |

## 命令行

本页相关的命令如下。全部参数见 [参考 · Semantic 本体与数据](cli-semantic.md)。webhook 的命令见 [参考 · 数据接入](cli-data.md)。

| 命令 | 做什么 |
| --- | --- |
| `aidc semantic ontology` | 看本体全貌 |
| `aidc semantic define <文件\|目录> [--dry-run]` | 整批提交定义 |
| `aidc semantic archive <apiName>` | 归档一个定义 |
| `aidc semantic publish --notes "…"` | 发布一个语义版本 |
| `aidc semantic releases` | 列出语义版本 |
| `aidc semantic branch create\|modify\|validate\|conflicts\|rebase\|propose` | 分支与提案 |
| `aidc semantic proposals`，`aidc semantic proposal <id>` | 列出提案，看一个提案 |
| `aidc semantic proposal approve\|reject\|merge <id>` | 批准、驳回、合并 |
| `aidc semantic approval-policy [set review\|yolo]` | 看或改审批策略 |
| `aidc semantic functions list\|publish` | 列出函数，发布一个函数版本 |
| `aidc semantic connectivity webhook put\|get\|delete\|test` | webhook 的建、看、删、手动试 |

## API

下表列出本页涉及的接口。前缀里的 `{命名空间}` 是组织的命名空间，例如 `cell-demo`。

| 方法 | 路径 | 做什么 |
| --- | --- | --- |
| GET、POST | `/api/v1/ontologies/{命名空间}/branches` | 分支列表；新建分支 |
| POST | `/api/v1/ontologies/{命名空间}/branches/{分支}/modify` | 修改分支上的定义。请求头 `x-aidc-dry-run: true` 只试跑 |
| GET | `/api/v1/ontologies/{命名空间}/proposals` | 提案列表 |
| POST | `/api/v1/ontologies/{命名空间}/branches/{分支}/proposals` | 开提案 |
| POST | `/api/v1/ontologies/{命名空间}/proposals/{id}/merge` | 合并提案 |
| GET、PUT | `/api/v1/ontologies/{命名空间}/approval-policy` | 审批策略。PUT 只给本组织的 developer 本人 |
| GET、POST | `/api/v1/ontologies/{命名空间}/functions` | 已发布的函数；发布一个版本。`?dryRun=true` 只校验 |
| GET、POST | `/api/v1/connectivity/webhooks?ontology={命名空间}` | webhook 列表；建 webhook |
| GET、PUT、DELETE | `/api/v1/connectivity/webhooks/{webhookRid}` | 看、改、删 webhook |
| POST | `/api/v1/connectivity/webhooks/{webhookRid}/execute` | 手动试 webhook。`dryRun` 为 true 只渲染 |

## 下一步

- [读写对象](data.md)：读对象、订阅变化、用 Action 改数据。
- [SQL 与数据库](sql.md)：用 SQL 查对象。
- [自动化](workflow.md)：数据变了触发 Action、函数或通知。
- [访问与安全](auth.md)：谁能看，Marking，安全策略。
- [数据接入](connect.md)：数据流，数据源，REST API 数据源。
- [自进化 SDK](evolve.md)：用户提的改进怎样变成语义改动。
