openxiangda-skill-kit 2.1.1 → 2.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/skills/openxiangda-v2/SKILL.md +1 -1
- package/skills/openxiangda-v2/references/backend.md +1 -1
- package/skills/openxiangda-v2/references/data-authz.md +15 -1
- package/skills/openxiangda-v2/references/delivery.md +4 -7
- package/skills/openxiangda-v2/references/development.md +21 -0
- package/skills/openxiangda-v2/references/frontend.md +37 -0
- package/skills/openxiangda-v2/references/public-access.md +81 -2
- package/skills/openxiangda-v2/references/testing.md +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda-skill-kit",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.3",
|
|
4
4
|
"description": "OpenXiangda 2.0 中文 AI 技能的校验、分发与安装。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"README.md"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"openxiangda-devkit-core": "2.
|
|
20
|
+
"openxiangda-devkit-core": "2.11.0"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"tsx": "4.23.12",
|
|
@@ -99,7 +99,7 @@ pnpm exec openxiangda --mcp-stdio --cwd <workspace>
|
|
|
99
99
|
|
|
100
100
|
平台拥有身份、授权、业务数据、环境和部署状态。应用只声明自己的模型、页面和规则;普通 CRUD 走 Data API,标准审批和通知按需声明,真实业务动作才启用 Nest。编译器生成契约,应用不改生成输出、不维护第二份权限或能力目录。菜单建议只供初次复制到应用声明,不是运行时自动发现。
|
|
101
101
|
|
|
102
|
-
匿名访问使用 frontend.publicAccess、createAnonymousPublicClient 与平台浏览器凭证,不建立 guest 角色或公开普通 Data API
|
|
102
|
+
匿名访问使用 frontend.publicAccess、createAnonymousPublicClient 与平台浏览器凭证,不建立 guest 角色或公开普通 Data API。提交策略的 `create` 必须配套 `draft`;只读外部数据使用 `public.list`/`public.read` 和显式 `publicRecordFields`,附件/图片/清洗后的富文本走平台代理 URL,子表用 `publicSubtableFields` 显式投影,不需要 draft,且不接受任意筛选、排序或投影。角色并集来自当前用户,Perspective 只收窄读取。
|
|
103
103
|
|
|
104
104
|
## 完成与失败
|
|
105
105
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# NestJS 后端
|
|
2
2
|
|
|
3
|
-
默认模板只包含 Web 和共享契约。只有需要执行服务端业务动作时才增加 NestJS。记录列表、详情、新增、编辑和删除直接由浏览器调用平台 Data API,不在 controller
|
|
3
|
+
默认模板只包含 Web 和共享契约。只有需要执行服务端业务动作时才增加 NestJS。记录列表、详情、新增、编辑和删除直接由浏览器调用平台 Data API,不在 controller 中重写一遍。启用前先按[判定是否真的需要 Nest 后端](development.md#backend-decision)逐行核对:幂等、时间窗、状态前置、角色核对、聚合、导入导出都有声明式答案;只有真实外部副作用或无法声明的跨资源不变量才是启用理由。`check` 会拒绝未以 `@OpenXiangdaOperation(appOperations.<code>)` 绑定已声明 operation 的应用路由。
|
|
4
4
|
|
|
5
5
|
平台网关验证当前用户完整的应用角色并集,并把经平台重验的角色、capability 与可选 Perspective 交给 Nest SDK。业务 controller 使用生成的 operation 合同和 capability 装饰器;平台仍是身份与授权的唯一所有者。请求作用域 `OpenXiangdaDataApiService` 自动继承 Perspective 读取投影;绕过 Data API 的自定义读取才使用 `@CurrentPerspective()` 显式投影。应用代码不替换身份、不保存平台凭据,也不建立第二套用户或权限状态。
|
|
6
6
|
|
|
@@ -41,7 +41,21 @@ impersonation token。mutation 必须携带 UUID `operationId`、`reason`,更
|
|
|
41
41
|
|
|
42
42
|
匿名外部访问不属于 RBAC 角色或 current-user 行策略。公开表单、续填、附件、重复校验和同一
|
|
43
43
|
浏览器的本人记录访问只通过[`frontend.publicAccess` 专用合同](public-access.md)开放;平台继续在
|
|
44
|
-
专用端点和 PostgreSQL/RLS
|
|
44
|
+
专用端点和 PostgreSQL/RLS 中强制匿名主体、字段、策略及提交回执边界。需要向外部发布目录、公告或
|
|
45
|
+
可用性列表时,使用同一合同的 `public.list`/`public.read` 与 `publicRecordFields`,明确绑定资源和
|
|
46
|
+
字段;`file`、`image` 和清洗后的 `text.rich` 可以公开,返回的托管文件引用只能通过匿名文件内容路由
|
|
47
|
+
读取,不暴露对象存储地址。子表字段必须在 `publicSubtableFields` 中再次选择子资源字段,例如:
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
publicRecordFields: ['name', 'cover', 'description', 'items'],
|
|
51
|
+
publicSubtableFields: { items: ['sku', 'quantity'] },
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
子表只支持一层、固定子字段和有界行数;嵌套子表、签名字段、未声明字段都会在编译或运行时拒绝。
|
|
55
|
+
公共读取不需要 `draft`,不继承角色权限,也不开放普通 Native Data API、where、排序、聚合或导出参数。
|
|
56
|
+
普通 Native Data API 的 `select`、`where`、批量、聚合和导出输入只适用于已认证用户或应用后端;把它暴露给匿名
|
|
57
|
+
浏览器会产生资源/字段枚举、条件推断、查询放大和文件 ID 猜测面。公共端点可以复用 Native RLS 和文件
|
|
58
|
+
绑定校验,但必须保留固定资源、固定字段、固定排序和固定分页的较小输入面。
|
|
45
59
|
|
|
46
60
|
数值边界直接声明在字段上,`min`/`max` 为闭区间,并且只允许用于
|
|
47
61
|
`number.integer` 和 `number.decimal`。跨字段约束声明在资源的
|
|
@@ -4,13 +4,10 @@
|
|
|
4
4
|
|
|
5
5
|
## 测试部署
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
本地构建仍是当前交付方式;源码提交存在不等于平台已独立验证制品由该提交构建。
|
|
7
|
+
源码托管仍可通过 `pnpm openxiangda source push` 提交和推送,但不是测试发布的前置步骤。
|
|
8
|
+
发布使用当前工作区内容,源码提交、分支名称和是否存在未提交修改不会阻塞测试环境;包元数据会保留实际来源信息。
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
开发开始时先同步主线并读取项目现状,开发完成包括提交、推送与主线整合。每个工作区保持一个写者;需要并行时使用独立目录并明确各任务范围。日常 dev/check 仍可验证未提交源码。没有 Git 远端的项目应先建立并绑定仓库再发布。
|
|
10
|
+
开发者可以从当前任务分支或本地工作区直接发布。团队是否要求合入默认分支属于协作规范,不由 Devkit 在每次发布时重复执行。
|
|
14
11
|
|
|
15
12
|
准备部署时直接执行 deploy,它已经包含兼容性预检、生成、检查、测试和构建。只想检查代码时使用 [check](testing.md),无需在 deploy 前重复运行全套检查。
|
|
16
13
|
|
|
@@ -37,7 +34,7 @@ pnpm openxiangda status <deployment-id> --watch
|
|
|
37
34
|
|
|
38
35
|
网络响应不确定时先查询原运行,不凭本地输出创建重复部署。平台部署成功后,仍需执行真实角色的业务验收。
|
|
39
36
|
|
|
40
|
-
|
|
37
|
+
重复发布直接使用当前源码重新构建。pnpm、Docker 和平台可以自行提供构建缓存,Devkit 不维护另一套工作区摘要或候选状态。提交响应不确定时使用原 DeploymentRun 的 status/logs 和 recovery 继续处理。
|
|
41
38
|
|
|
42
39
|
## 测试环境验收
|
|
43
40
|
|
|
@@ -27,6 +27,27 @@
|
|
|
27
27
|
- 标准审批、待办与通知:按需声明平台能力,见[工作流](workflow-events.md)。
|
|
28
28
|
- 真实事务或外部集成:使用[按需后端](backend.md),不为每张表重写 CRUD 控制器。
|
|
29
29
|
|
|
30
|
+
### 判定是否真的需要 Nest 后端 {#backend-decision}
|
|
31
|
+
|
|
32
|
+
想写后端接口时,先按顺序核对平台已有的声明式答案;命中前几行的需求不得启用 Nest。
|
|
33
|
+
普通数据增删改查永远由浏览器直接调用平台 Data API 或标准 CRUD 页面完成,
|
|
34
|
+
应用 controller 不做记录列表、详情、新增、编辑、删除的转发。
|
|
35
|
+
|
|
36
|
+
| 你以为需要写后端 | 平台已有的声明式答案 | 参考 |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| 列表、筛选、排序、分页接口 | `createNativeResourceClient` 的 `list`,服务端条件树与分页 | [前端数据访问](frontend.md#data-access) |
|
|
39
|
+
| 新增 / 编辑 / 删除接口 | 标准 CRUD 页面,或同一客户端的 `create` / `update` / `remove`(`expectedRevision` 乐观锁) | [前端数据访问](frontend.md#data-access) |
|
|
40
|
+
| 提交防重、幂等重试 | `transactNativeData` / 事务请求自带 `idempotencyKey` 幂等回执 | [前端数据访问](frontend.md#data-access)、[按需后端](backend.md#business-action) |
|
|
41
|
+
| 时间窗、状态前置、指定人角色校验 | 平台事务守卫:`operation-time`、`record-assert`、`record-exists`、`role-member` | [按需后端](backend.md#business-action) |
|
|
42
|
+
| 统计报表数据 | Data API 服务端聚合 `batchAggregateNativeResources`(单个指标也用它),前端不拉全量求和 | [前端](frontend.md#component-selection) |
|
|
43
|
+
| 导入 / 导出 | 标准 CRUD 的 `import` / `export` 动作声明 | [业务模块](application-foundation.md) |
|
|
44
|
+
| 跨模型原子写、外部 API、硬件或第三方推送 | Nest 具名 operation + 平台事务,必要时事务内 `emitEvent` | [按需后端](backend.md) |
|
|
45
|
+
|
|
46
|
+
启用 Nest 的唯一充分条件是:真实外部副作用,或现有守卫无法声明的跨资源业务不变量,
|
|
47
|
+
且该动作已作为 operation 声明能力(`kind: 'backend'`)并由角色显式引用。
|
|
48
|
+
"需要一点校验""需要默认值""需要联动查询"不是启用理由;校验优先字段规则与事务守卫,
|
|
49
|
+
默认值优先服务端字段责任,联动查询优先 Data API 条件树。
|
|
50
|
+
|
|
30
51
|
## 实施与交接 {#iteration}
|
|
31
52
|
|
|
32
53
|
开发使用 `pnpm openxiangda dev`,过程中运行必要的聚焦测试。交接前按[检查与验收](testing.md)验证;授权发布后按[交付](delivery.md)部署。失败保留错误码、位置和原始候选,依据平台恢复指令继续。
|
|
@@ -63,6 +63,43 @@ capability、应用角色和数据策略。前端只根据当前登录用户完
|
|
|
63
63
|
可替换 Data API adapter。不要调用自定义 Nest CRUD、Function 或 Workflow 来绕过
|
|
64
64
|
Data API。只有真正需要事务或外部系统的动作才使用同源 `/api`。
|
|
65
65
|
|
|
66
|
+
### 自定义页面消费平台数据 {#data-access}
|
|
67
|
+
|
|
68
|
+
自定义报表、工具页和用户端页面从 `openxiangda/core` 导入 `createNativeResourceClient`,
|
|
69
|
+
用生成契约里的 surface 直接获得该资源的权威读写客户端;行、字段与操作授权由平台在
|
|
70
|
+
每次请求时执行,页面不需要也不得复制权限逻辑:
|
|
71
|
+
|
|
72
|
+
```tsx
|
|
73
|
+
import { createNativeResourceClient } from 'openxiangda/core';
|
|
74
|
+
import { resourceSurfaces } from '@app/contracts';
|
|
75
|
+
|
|
76
|
+
const records = createNativeResourceClient('records', resourceSurfaces.records);
|
|
77
|
+
|
|
78
|
+
// 服务端过滤、排序、分页;字段必须已声明,未声明字段直接报错
|
|
79
|
+
const page = await records.list({
|
|
80
|
+
page: 1,
|
|
81
|
+
pageSize: 20,
|
|
82
|
+
where: { field: 'enabled', operator: 'eq', value: true },
|
|
83
|
+
sort: { field: 'createdAt', order: 'desc' },
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
const record = await records.get(id);
|
|
87
|
+
await records.create(data);
|
|
88
|
+
await records.update(id, expectedRevision, data); // revision 冲突时明确报错
|
|
89
|
+
await records.remove(id, expectedRevision);
|
|
90
|
+
await records.upload('attachment', file, recordId);
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
跨模型原子写使用 `transactNativeData(operations, idempotencyKey)`:一次平台事务提交
|
|
94
|
+
多个资源操作,携带幂等键,不确定的响应复用同一载荷重试,不产生第二份业务效果。
|
|
95
|
+
多指标统计使用 `batchAggregateNativeResources` 在服务端聚合。导出使用
|
|
96
|
+
`records.exportCsv(query, select)`,与列表共用同一查询条件。
|
|
97
|
+
|
|
98
|
+
要求服务端校验、状态前置或角色核对时,优先事务守卫(见
|
|
99
|
+
[判定是否真的需要 Nest 后端](development.md#backend-decision));只有在真实外部
|
|
100
|
+
副作用下才声明 Nest operation。自写 controller 转发单一资源的增删改查无法通过 `check`:
|
|
101
|
+
每个应用路由必须以 `@OpenXiangdaOperation(appOperations.<code>)` 绑定已声明的 operation。
|
|
102
|
+
|
|
66
103
|
默认仪器模块有 30 个字段,其中 `id/revision` 是 Data API 系统字段,28 个业务
|
|
67
104
|
字段由资源声明。新增、编辑和详情共用同一份字段元数据。五个边界字段使用五个独立
|
|
68
105
|
capability,不使用角色名或影子字段判断。
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
OpenXiangda 2.0 支持没有平台账号的外部访客打开一个明确公开的用户页面,保存并续填草稿、
|
|
4
4
|
上传平台托管附件、执行具名重复校验、正式提交,并在同一浏览器中查看自己已提交的列表和详情。
|
|
5
|
+
应用也可以显式发布某个资源的部分记录字段,让外部浏览器分页查询公开记录或读取一条公开记录。
|
|
5
6
|
|
|
6
7
|
该能力识别的是“持有同一个平台 HttpOnly 浏览器凭证的访问者”,不是经过实名验证的自然人。
|
|
7
8
|
清除 Cookie、无痕模式、另一浏览器或另一设备都会成为新的匿名访问者,不能找回原草稿和记录。
|
|
@@ -21,7 +22,7 @@ User-Agent 或浏览器指纹猜测同一个人。
|
|
|
21
22
|
## 应用声明
|
|
22
23
|
|
|
23
24
|
资源仍然按普通 Native Resource 声明。公开能力只在一个静态 `surface: 'user'` 路由上增加一个
|
|
24
|
-
严格有界的 `frontend.publicAccess`
|
|
25
|
+
严格有界的 `frontend.publicAccess` 策略;同一路由可以按设备或资源声明多条策略,调用方必须带策略码:
|
|
25
26
|
|
|
26
27
|
```ts
|
|
27
28
|
export default defineOpenXiangdaApp({
|
|
@@ -104,9 +105,83 @@ export default defineOpenXiangdaApp({
|
|
|
104
105
|
| `create` | 以幂等键正式提交当前草稿 |
|
|
105
106
|
| `own.list` | 分页查看同一浏览器正式提交的记录 |
|
|
106
107
|
| `own.read` | 查看同一浏览器的一条正式提交详情 |
|
|
108
|
+
| `public.list` | 分页查看当前策略明确发布的资源记录 |
|
|
109
|
+
| `public.read` | 读取当前策略明确发布的一条资源记录 |
|
|
107
110
|
|
|
108
111
|
`own.list` 和 `own.read` 不是一般查询权限。服务端固定注入匿名主体、当前公开策略和已提交草稿
|
|
109
|
-
回执条件,不接受调用方的 where
|
|
112
|
+
回执条件,不接受调用方的 where、排序、投影或统计表达式。`public.list` 和 `public.read` 同样不是
|
|
113
|
+
一般查询权限:它们只读取策略绑定资源在当前租户、应用和环境下的记录,服务端固定按创建时间和 id
|
|
114
|
+
倒序分页,只返回 `publicRecordFields` 中显式列出的字段和记录 `id`。附件、图片和清洗后的富文本
|
|
115
|
+
通过平台托管文件路由公开,不返回对象存储地址。子表字段必须在 `publicSubtableFields` 中再次显式
|
|
116
|
+
列出子资源字段,服务端按声明顺序和行数上限返回一层子表数据。签名字段仍不公开。当前不支持调用方
|
|
117
|
+
筛选、排序、聚合或导出。
|
|
118
|
+
|
|
119
|
+
## `draft` 与公共读取
|
|
120
|
+
|
|
121
|
+
`draft` 是匿名提交的服务端事务载体,不是“外部访问”本身,也不是公共读取的前置条件。提交表单时,
|
|
122
|
+
平台需要先把不完整的输入保存到当前匿名浏览器的草稿,并用 `revision` 做并发控制;附件元数据绑定
|
|
123
|
+
到草稿;最终 `create` 会在同一数据库事务中锁定草稿、重新执行必填和重复校验、创建业务记录、标记
|
|
124
|
+
草稿已提交,并用幂等键保证不重复创建。因此声明 `create` 必须同时声明 `draft: { enabled: true }`,
|
|
125
|
+
而且同一策略的 `draft.read` 与 `draft.update` 必须成对出现。
|
|
126
|
+
|
|
127
|
+
公共只读场景不需要草稿。只声明 `public.list`/`public.read` 和 `publicRecordFields` 的策略可以直接
|
|
128
|
+
调用公共查询;它不会获得 `create`、`draft`、`own.*` 或普通 Native Data API 权限。不要为了查询已发布
|
|
129
|
+
数据创建一个“空草稿”,也不要把 `draft id` 传给浏览器。
|
|
130
|
+
|
|
131
|
+
例如,目录页面可以只发布明确选定的字段:
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
{
|
|
135
|
+
code: 'catalog-public',
|
|
136
|
+
routeCode: 'catalog',
|
|
137
|
+
mode: 'anonymous',
|
|
138
|
+
resourceCode: 'catalog-items',
|
|
139
|
+
operations: ['public.list', 'public.read'],
|
|
140
|
+
fields: ['name', 'category', 'available', 'internalNote'],
|
|
141
|
+
publicRecordFields: ['name', 'category', 'available', 'items'],
|
|
142
|
+
publicSubtableFields: { items: ['sku', 'quantity'] },
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
`publicRecordFields` 必须是 `fields` 和资源字段的子集;附件、图片和 `text.rich` 可公开,签名仍被
|
|
147
|
+
拒绝。公开子表字段必须配置 `publicSubtableFields`,其键是父资源的子表字段,值是子资源字段列表;
|
|
148
|
+
编译器会拒绝未声明字段、嵌套子表和缺少子字段投影。公共读取沿用明确公开的 `frontend.publicAccess`
|
|
149
|
+
路由和匿名浏览器凭证,不创建 guest 角色或虚拟内部用户。
|
|
150
|
+
|
|
151
|
+
需要隐藏停用、归档或租户标记记录时,使用固定 `publicFilters`,由服务端对每次 `public.list`/
|
|
152
|
+
`public.read` 强制追加。当前只支持最多 16 个不同字段的 `eq` 等值条件,字段必须属于策略的
|
|
153
|
+
`fields` 且仅允许布尔、文本、数值、日期和时间标量;调用方不能覆盖、追加或删除这些条件:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
publicFilters: [{ field: 'enabled', operator: 'eq', value: true }]
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
匿名创建需要平台生成的不可预测字段时,使用 `serverGeneratedFields`。这些字段不属于
|
|
160
|
+
`fields`,调用方不能在草稿中写入;提交事务会由平台生成随机值并在提交回执的 `generated`
|
|
161
|
+
对象中返回。`random-token` 只适用于不承载身份信息的核验令牌等用途:
|
|
162
|
+
|
|
163
|
+
```ts
|
|
164
|
+
serverGeneratedFields: [{ field: 'qrToken', kind: 'random-token' }]
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
需要跨资源复核预约窗口等业务不变量时,可声明 `schedule`,绑定两个只读公开策略和资源字段。
|
|
168
|
+
平台会在最终创建事务中重新读取启用校区与规则,校验星期、日期范围、提前小时数和离散时段;页面端
|
|
169
|
+
校验只能改善体验,不能替代这次服务端复核。
|
|
170
|
+
|
|
171
|
+
子表中的文件引用会自动带上受控的 `resourceCode` 与父字段绑定;应用如需为附件生成下载地址,使用
|
|
172
|
+
`fileContentUrl(fileId, disposition, variant, resourceCode, parentFieldCode)`,不要自行拼接文件路径。
|
|
173
|
+
|
|
174
|
+
## 为什么不开放普通 Native Data API
|
|
175
|
+
|
|
176
|
+
普通 Native Data API 是内部或应用后端的可信数据边界,允许调用方提交
|
|
177
|
+
`select`、`where`、`order`、批量查询、聚合和导出,并按当前登录用户角色执行行列权限。匿名
|
|
178
|
+
公开发布的语义不同:它必须只绑定一个资源和不可变字段白名单,不接受调用方筛选、排序、聚合、
|
|
179
|
+
导出或自带角色,也必须把文件绑定到公开记录和公开字段后再读取。
|
|
180
|
+
|
|
181
|
+
直接把普通 Native Data API 暴露给浏览器会允许枚举内部资源和字段、通过筛选和计数推断未公开数据,
|
|
182
|
+
放大查询资源消耗,并增加文件 ID 猜测、审计字段泄露和权限合同混用的风险。因此公共端点继续是
|
|
183
|
+
专用的 `public.list`/`public.read`;底层可以复用 Native 的 RLS 和文件所有权校验,但不把 Native
|
|
184
|
+
Data API 的输入面开放给匿名调用方。
|
|
110
185
|
|
|
111
186
|
## 页面客户端
|
|
112
187
|
|
|
@@ -133,6 +208,10 @@ const receipt = await client.submit(withPhoto.revision, crypto.randomUUID());
|
|
|
133
208
|
|
|
134
209
|
const page = await client.listOwn({ pageSize: 20 });
|
|
135
210
|
const detail = await client.getOwn(receipt.recordId);
|
|
211
|
+
|
|
212
|
+
// 只读公开目录不需要先读取或保存 draft。
|
|
213
|
+
const publicPage = await client.listPublic({ pageSize: 20 });
|
|
214
|
+
const publicDetail = await client.getPublic(publicPage.items[0].data.id as string);
|
|
136
215
|
```
|
|
137
216
|
|
|
138
217
|
必须先 `bootstrap()`。草稿更新始终使用最近返回的 revision,冲突时重新读取,不能覆盖写。
|
|
@@ -18,7 +18,7 @@ CI、离线开发或尚未发布的候选包使用 `pnpm openxiangda check --loc
|
|
|
18
18
|
|
|
19
19
|
检查会写本地生成结果并按需初始化后端,不是只读操作。前置阶段失败后,下游阶段标为 skipped,不继续构建或上传。保留错误码、pointer、details 和下一步,修正原因后重试。
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
每次检查都直接执行当前工作区声明的 check/test/build 脚本;构建工具和包管理器可以自行使用缓存。目标平台的权限、密钥和模型条件仍在正式检查和部署前预检。Devkit 不维护额外的工作区摘要凭据,也不会因为分支、提交或文档变化引入候选复用分支。
|
|
22
22
|
|
|
23
23
|
成功检查返回 `sealedArtifact.state: check-did-not-seal`、`sealed: false`、`usableForDeploy: false`。旧 AppPackage 不是当前检查结果。要发布测试环境可直接运行 deploy,它已包含完整检查;不要连续重复执行 check、test 和 build。
|
|
24
24
|
|