openxiangda 2.25.3 → 2.26.0

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.
Files changed (33) hide show
  1. package/dist/browser/components/resource/useResourceFormDrafts.d.ts.map +1 -1
  2. package/dist/browser/components/workflow/StandardWorkflowPages.d.ts.map +1 -1
  3. package/dist/browser/components/workflow/StandardWorkflowPages.js +145 -16
  4. package/dist/browser/components/workflow/StandardWorkflowPages.js.map +1 -1
  5. package/dist/browser/platform-client.d.ts +25 -1
  6. package/dist/browser/platform-client.d.ts.map +1 -1
  7. package/dist/browser/platform-client.js +62 -27
  8. package/dist/browser/platform-client.js.map +1 -1
  9. package/dist/browser/workflow-submission-recovery.d.ts +16 -0
  10. package/dist/browser/workflow-submission-recovery.d.ts.map +1 -0
  11. package/dist/browser/workflow-submission-recovery.js +56 -0
  12. package/dist/browser/workflow-submission-recovery.js.map +1 -0
  13. package/dist/nest.d.ts +2 -2
  14. package/dist/nest.d.ts.map +1 -1
  15. package/dist/nest.js +1 -1
  16. package/dist/nest.js.map +1 -1
  17. package/dist/react.d.ts +1 -1
  18. package/dist/react.d.ts.map +1 -1
  19. package/dist/react.js +1 -1
  20. package/dist/react.js.map +1 -1
  21. package/documentation/backend.md +42 -13
  22. package/documentation/getting-started.md +7 -7
  23. package/documentation/manifest.json +5 -5
  24. package/documentation/testing.md +15 -0
  25. package/documentation/upgrading.md +12 -0
  26. package/package.json +31 -22
  27. package/releases/2.26.0.json +41 -0
  28. package/skills/manifest.json +1 -1
  29. package/skills/openxiangda-v2/SKILL.md +4 -4
  30. package/skills/openxiangda-v2/references/backend.md +42 -13
  31. package/skills/openxiangda-v2/references/getting-started.md +7 -7
  32. package/skills/openxiangda-v2/references/testing.md +15 -0
  33. package/skills/openxiangda-v2/references/upgrading.md +12 -0
package/dist/react.d.ts CHANGED
@@ -16,7 +16,7 @@ export * from './browser/Shell';
16
16
  export * from './browser/resource-definitions';
17
17
  export * from './browser/workflow-definitions';
18
18
  export * from './browser/workflow-launch';
19
- export { createResourceFormDraftClient, createWorkflowFormDraftClient, type ResourceFormDraftWorkflowScope, type ResourceFormDraft, createAnonymousPublicClient, applicationFileIntentUrl, executeApplicationOperation, issueApplicationFileIntent, loadApplicationOperationSurfaces, loadSubjectReadSurface, logoutCurrentUser, type AnonymousPublicDraft, type AnonymousPublicRecord, } from './browser/platform-client';
19
+ export { OpenXiangdaPlatformRequestError, platformRequestDiagnostic, type PlatformRequestContext, resolveBusinessProcessOriginal, createResourceFormDraftClient, createWorkflowFormDraftClient, type ResourceFormDraftWorkflowScope, type ResourceFormDraft, createAnonymousPublicClient, applicationFileIntentUrl, executeApplicationOperation, issueApplicationFileIntent, loadApplicationOperationSurfaces, loadSubjectReadSurface, logoutCurrentUser, type AnonymousPublicDraft, type AnonymousPublicRecord, } from './browser/platform-client';
20
20
  export type { ApplicationOperationReceiptV2, ApplicationLogoutReceiptV2, ApplicationFileIntentV2, ApplicationOperationSurfaceCatalogV2, ApplicationOperationSurfaceV2, WorkflowCommandResult, } from 'openxiangda-contracts/browser';
21
21
  export * from './browser/components/resource/GeneratedResourceCrud';
22
22
  export * from './browser/components/resource/ResourceBatchActions';
@@ -1 +1 @@
1
- {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA,OAAO,iCAAiC,CAAC;AAEzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0CAA0C,CAAC;AACzD,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACrG,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAC7B,KAAK,8BAA8B,EACnC,KAAK,iBAAiB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,EAChC,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,EACvB,oCAAoC,EACpC,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,cAAc,qDAAqD,CAAC;AACpE,cAAc,oDAAoD,CAAC;AACnE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qCAAqC,CAAC;AACpD,cAAc,qDAAqD,CAAC;AACpE,mBAAmB,6DAA6D,CAAC"}
1
+ {"version":3,"file":"react.d.ts","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA,OAAO,iCAAiC,CAAC;AAEzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0CAA0C,CAAC;AACzD,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,KAAK,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACrG,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EACzB,KAAK,sBAAsB,EAC3B,8BAA8B,EAC9B,6BAA6B,EAC7B,6BAA6B,EAC7B,KAAK,8BAA8B,EACnC,KAAK,iBAAiB,EACtB,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,EAChC,sBAAsB,EACtB,iBAAiB,EACjB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,GAC3B,MAAM,2BAA2B,CAAC;AACnC,YAAY,EACV,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,EACvB,oCAAoC,EACpC,6BAA6B,EAC7B,qBAAqB,GACtB,MAAM,+BAA+B,CAAC;AACvC,cAAc,qDAAqD,CAAC;AACpE,cAAc,oDAAoD,CAAC;AACnE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qCAAqC,CAAC;AACpD,cAAc,qDAAqD,CAAC;AACpE,mBAAmB,6DAA6D,CAAC"}
package/dist/react.js CHANGED
@@ -16,7 +16,7 @@ export * from './browser/Shell';
16
16
  export * from './browser/resource-definitions';
17
17
  export * from './browser/workflow-definitions';
18
18
  export * from './browser/workflow-launch';
19
- export { createResourceFormDraftClient, createWorkflowFormDraftClient, createAnonymousPublicClient, applicationFileIntentUrl, executeApplicationOperation, issueApplicationFileIntent, loadApplicationOperationSurfaces, loadSubjectReadSurface, logoutCurrentUser, } from './browser/platform-client';
19
+ export { OpenXiangdaPlatformRequestError, platformRequestDiagnostic, resolveBusinessProcessOriginal, createResourceFormDraftClient, createWorkflowFormDraftClient, createAnonymousPublicClient, applicationFileIntentUrl, executeApplicationOperation, issueApplicationFileIntent, loadApplicationOperationSurfaces, loadSubjectReadSurface, logoutCurrentUser, } from './browser/platform-client';
20
20
  export * from './browser/components/resource/GeneratedResourceCrud';
21
21
  export * from './browser/components/resource/ResourceBatchActions';
22
22
  export * from './browser/components/resource/StandardResourcePages';
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA,OAAO,iCAAiC,CAAC;AAEzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0CAA0C,CAAC;AACzD,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAmC,MAAM,4BAA4B,CAAC;AACrG,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,6BAA6B,EAC7B,6BAA6B,EAG7B,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,EAChC,sBAAsB,EACtB,iBAAiB,GAGlB,MAAM,2BAA2B,CAAC;AASnC,cAAc,qDAAqD,CAAC;AACpE,cAAc,oDAAoD,CAAC;AACnE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qCAAqC,CAAC;AACpD,cAAc,qDAAqD,CAAC"}
1
+ {"version":3,"file":"react.js","sourceRoot":"","sources":["../src/react.ts"],"names":[],"mappings":"AAAA,OAAO,iCAAiC,CAAC;AAEzC,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0CAA0C,CAAC;AACzD,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAmC,MAAM,4BAA4B,CAAC;AACrG,cAAc,kCAAkC,CAAC;AACjD,cAAc,iBAAiB,CAAC;AAChC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,gCAAgC,CAAC;AAC/C,cAAc,2BAA2B,CAAC;AAC1C,OAAO,EACL,+BAA+B,EAC/B,yBAAyB,EAEzB,8BAA8B,EAC9B,6BAA6B,EAC7B,6BAA6B,EAG7B,2BAA2B,EAC3B,wBAAwB,EACxB,2BAA2B,EAC3B,0BAA0B,EAC1B,gCAAgC,EAChC,sBAAsB,EACtB,iBAAiB,GAGlB,MAAM,2BAA2B,CAAC;AASnC,cAAc,qDAAqD,CAAC;AACpE,cAAc,oDAAoD,CAAC;AACnE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qDAAqD,CAAC;AACpE,cAAc,qCAAqC,CAAC;AACpD,cAAc,qDAAqD,CAAC"}
@@ -41,6 +41,15 @@ SDK 继承当前环境与身份,平台沿用发起人或既有超级管理员
41
41
  `items/nextCursor`,分页与多次流程的选择规则见[前端](frontend.md)。找回后使用原
42
42
  `receipt/poll/surface`;查询不重放提交、不生成第二份命令状态。
43
43
 
44
+ 连 commandId 都没收到时,用同一动作的 `businessProcess.resolveOriginal({ workflowCode,
45
+ idempotencyKey })` 查询原操作。此能力需要 `business-process.original-resolution` 1.0.0。
46
+ `committed` 才有可信回执;`not_observed` 可能仍在提交,不能据此生成新键或宣称回滚。
47
+ 前端可用 `resolveBusinessProcessOriginal`(`openxiangda/react`),传原 workflowCode、
48
+ operationCode、idempotencyKey;SDK 绑定当前环境并核验返回关联。Named Action 如果业务无需
49
+ 审批,没有流程回执并不代表业务没写入,应沿该动作自身回执诊断。
50
+ 标准 PC/移动发起页在响应未知时保留原操作定位信息,刷新可继续查询;同一页面、原身份和
51
+ 版本内可手动重试冻结的标准输入,绝不自动重发或悄悄换键。
52
+
44
53
  自定义表单页若先用 `createResourceFormDraftClient` 保存认证草稿,并由 Named Action
45
54
  提交业务记录和流程,则在同一次 `OpenXiangdaBusinessProcessService.commit` 中传入
46
55
  `formDraft: { resourceCode, id, expectedRevision, mode, recordId?, viewCode? }`。草稿必须
@@ -101,21 +110,28 @@ data: {
101
110
 
102
111
  ### 幂等冲突复核 {#idempotency-recovery}
103
112
 
104
- 同一 `idempotencyKey` 要求内容指纹一致。update 事务携带 `expectedRevision`,重试时 revision 已前进会触发 409 `OPENXIANGDA_NATIVE_DATA_IDEMPOTENCY_CONFLICT`。捕获后回读当前状态确认效果已生效,按幂等结果返回;不要换新键重试:
113
+ 同一 `idempotencyKey` 要求内容指纹一致。冻结首次请求的 operations、guards、expectedRevision、主体、环境和版本上下文;重试不能重新计算这些值。平台原回执的 `replayed` 才是重放成功证据。业务记录已经变化,本身不会导致原请求的幂等内容冲突;重新读取 revision 并改变请求才会。
114
+
115
+ `isIdempotencyConflict(error)` 只识别 409 `OPENXIANGDA_NATIVE_DATA_IDEMPOTENCY_CONFLICT`,不证明首次请求已成功。保留原操作并核对原回执;结果不明时显示“结果待确认”,不能把当前记录状态拼成伪造的成功回执,也不能换新键重试。部署 Head 改变时先恢复原上下文,不把同一键发送到另一版本当作原请求恢复。
116
+
117
+ ### 使用生成类型绑定资源 {#typed-resources}
118
+
119
+ 工具生成的共享契约导出 `ResourceTypes`;使用项目锁定版本的 `pnpm openxiangda check` 验证接入。三种 Nest 数据服务均保留原主体;当前用户业务优先用当前用户服务,具名业务动作使用业务服务。
105
120
 
106
121
  ```ts
107
- import { isIdempotencyConflict } from 'openxiangda/nest';
108
-
109
- try {
110
- result = await this.data.transaction(idempotentTransaction(key, operations, guards));
111
- } catch (error) {
112
- if (isIdempotencyConflict(error) && alreadyApplied(await this.data.get(...))) {
113
- return { idempotencyKey: key, replayed: true, ...currentState };
114
- }
115
- throw error;
116
- }
122
+ import type { ResourceTypes } from '@app/contracts';
123
+
124
+ const resources = this.data.resources<ResourceTypes>();
125
+ const requests = resources('repair-requests');
126
+ const record = await requests.get(input.id);
127
+ return requests.update(record.data.id, {
128
+ expectedRevision: record.data.revision,
129
+ data: { assignedTechnician: userSnapshot(input.technicianId) },
130
+ });
117
131
  ```
118
132
 
133
+ 资源名、写入字段、引用形状和 query 的字段/排序键会在 TypeScript 检查时验证;示例字段须由自己的模型声明。get/create/update/delete 保留 `data` 信封,revision 位于 `record.data.revision`。query 返回分页的 `items`。字段权限可能隐藏业务字段,所以读取类型保留这些字段可缺失的事实;应用必须按权限和必需字段做有意义的提示。该包装不会自动重试、修改 revision 或提升权限。运行时仍由平台校验所有输入。
134
+
119
135
  事务守卫的 `errorCode` 必须匹配 `^OPENXIANGDA_[A-Z0-9_]{1,96}$`,例如 `OPENXIANGDA_REPAIR_REQUEST_NOT_PENDING`。
120
136
 
121
137
  ## 在同一事务中引用前序 create 生成的 id {#transaction-references}
@@ -161,8 +177,21 @@ platformAccess: { roleAssertions: { roleCodes: ['technician'] } }
161
177
  ```
162
178
 
163
179
  `technician` 必须存在于本应用 `authz.roles`,最多声明 20 个角色。应用管理员身份
164
- 不自动代表维修角色。人员候选可以使用已有且已委托管理范围的成员查询;这项声明
165
- 本身不授予成员管理或人员目录权限。
180
+ 不自动代表维修角色。经办人使用请求作用域 `OpenXiangdaBusinessDirectoryService` 查询
181
+ 本动作声明的候选,无需成员管理权:
182
+
183
+ ```ts
184
+ const page = await businessDirectory.assignmentCandidates({
185
+ roleCode: 'technician', keyword: input.keyword, limit: 20,
186
+ ...(input.cursor ? { cursor: input.cursor } : {}),
187
+ });
188
+ // page.items 仅有 value/label;下一页沿用同一关键词和 page.nextCursor。
189
+ ```
190
+
191
+ 这项可选能力需要目标平台 `directory.assignment-candidates` 1.0.0。环境由 SDK 绑定,
192
+ 禁止传入任意环境或账号。平台只返回生效、未过期、正常且未锁定的成员,验证账号与正式
193
+ 账号隔离。游标绑定环境 Head、调用者、动作和角色,收到上下文变化错误后清空游标重新查询。
194
+ 候选结果只用于选人;提交时仍使用下面的事务条件,不能凭查询结果绕过重新核验。
166
195
 
167
196
  在 `OpenXiangdaBusinessDataApiService` 的同一次事务中表达业务状态与目标角色:
168
197
 
@@ -68,10 +68,10 @@ MCP 服务随项目根包一起安装,AI 客户端的 stdio 连接仍需配置
68
68
  以下命令的版本占位符由随包资料替换为该根包的精确版本。网站源码阅读者应先确认要使用的发行版本。
69
69
 
70
70
  ```bash
71
- pnpm dlx openxiangda@2.25.3 skill install --force
72
- pnpm dlx openxiangda@2.25.3 auth status --base-url <平台地址> --json
73
- pnpm dlx openxiangda@2.25.3 login --cwd my-app --base-url https://platform.example.com
74
- pnpm dlx openxiangda@2.25.3 create my-app --base-url https://platform.example.com
71
+ pnpm dlx openxiangda@2.26.0 skill install --force
72
+ pnpm dlx openxiangda@2.26.0 auth status --base-url <平台地址> --json
73
+ pnpm dlx openxiangda@2.26.0 login --cwd my-app --base-url https://platform.example.com
74
+ pnpm dlx openxiangda@2.26.0 create my-app --base-url https://platform.example.com
75
75
  cd my-app
76
76
  pnpm openxiangda context --json
77
77
  pnpm openxiangda dev
@@ -174,9 +174,9 @@ MCP 的 `docs_read` 可以读取本说明,当前没有独立的源码操作 MC
174
174
  无需本地工作区,使用本 Skill 随包精确版本或已安装的对应 CLI:
175
175
 
176
176
  ```bash
177
- pnpm dlx openxiangda@2.25.3 auth status --base-url <平台> --json
178
- pnpm dlx openxiangda@2.25.3 source resolve <仓库URL> --base-url <平台> --json
179
- pnpm dlx openxiangda@2.25.3 source clone <仓库URL> <新目录> --base-url <平台> --json
177
+ pnpm dlx openxiangda@2.26.0 auth status --base-url <平台> --json
178
+ pnpm dlx openxiangda@2.26.0 source resolve <仓库URL> --base-url <平台> --json
179
+ pnpm dlx openxiangda@2.26.0 source clone <仓库URL> <新目录> --base-url <平台> --json
180
180
  ```
181
181
 
182
182
  登录缺失或站点不匹配时,先按该平台执行 login。resolve 根据平台已经登记的绑定返回
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "schemaVersion": "openxiangda.documentation/v1",
3
- "version": "2.25.3",
3
+ "version": "2.26.0",
4
4
  "topics": [
5
5
  {
6
6
  "id": "getting-started",
7
7
  "title": "安装与开始开发",
8
8
  "file": "getting-started.md",
9
- "sha256": "8ec6073f51f573b007662043a24e793e09893d4168168629598dfdc7b53c0330"
9
+ "sha256": "3a44fb825672842b9013e9846dbd7312f282d59ce365c4e8457b83eba4292b43"
10
10
  },
11
11
  {
12
12
  "id": "product-design",
@@ -90,7 +90,7 @@
90
90
  "id": "backend",
91
91
  "title": "按需后端与业务动作",
92
92
  "file": "backend.md",
93
- "sha256": "b19d6f76a28de2539f8752d0b99fc3fcf0424c1ecb2b3dd6a4fb3e5e84e41806"
93
+ "sha256": "fdf89d2dfd6dfbfe692f43ff55e8975f64540f27609fda44a245e95eda72e870"
94
94
  },
95
95
  {
96
96
  "id": "administration",
@@ -102,7 +102,7 @@
102
102
  "id": "testing",
103
103
  "title": "检查与真实业务验收",
104
104
  "file": "testing.md",
105
- "sha256": "c40017e019f3ff2ba19b0995c4bfd597d6cc33164faab6a754692f810849429c"
105
+ "sha256": "bc16ffa07fae9ddf17baf3ca99f7076aeee5976244864e46c701816c77ee9abd"
106
106
  },
107
107
  {
108
108
  "id": "delivery",
@@ -114,7 +114,7 @@
114
114
  "id": "upgrading",
115
115
  "title": "版本升级与资料刷新",
116
116
  "file": "upgrading.md",
117
- "sha256": "ec2bffabbc80da7e79007867fcd915e1a56a4e4fd85e83df98a405f672beaf74"
117
+ "sha256": "c51c30699d9076f2051d8ee26a91f74c879e4d3b2a6f56ac8c68f4355baf36b2"
118
118
  },
119
119
  {
120
120
  "id": "cli",
@@ -64,6 +64,21 @@ pnpm openxiangda accept --plan .openxiangda/acceptance-plan.json --json
64
64
 
65
65
  记录源码/包版本、AppVersion、环境、角色、预期及实际结果、必要请求标识。区分本地检查、分发安装、部署激活与业务验收。某项未执行时说明原因,不将其写成通过。
66
66
 
67
+ ## 复制请求诊断 {#request-diagnostics}
68
+
69
+ 标准浏览器请求错误保留服务端 requestId,文件导出及权限读取重试耗尽也使用同一错误类型。自定义页面通过公开入口读取固定格式诊断:
70
+
71
+ ```ts
72
+ import { platformRequestDiagnostic } from 'openxiangda/react';
73
+
74
+ function supportDetails(error: unknown) {
75
+ const diagnostic = platformRequestDiagnostic(error);
76
+ return diagnostic ? JSON.stringify(diagnostic, null, 2) : null;
77
+ }
78
+ ```
79
+
80
+ 将这段结果放入当前操作的错误详情,附应用版本和原 operationId/DeploymentRun;不要复制 Cookie、令牌、完整请求正文或原始响应。诊断包含错误码、请求路径(无 query)、方法、站点内应用/环境、观测时间和合法 requestId。网络未收到响应时 requestId 为 null,不能编造关联标识。该信息不等于提交结果:写入未知时查询原操作,保留原键与原输入;不要自动换键再写。Nest SDK 的平台错误已有 `request` 上下文,平台管理仍通过授权范围内的日志/支持通道检索。
81
+
67
82
  ## 并发执行
68
83
 
69
84
  同一工作区的公共 check 和测试 deploy 共享本地互斥锁,前一个命令结束后才能启动下一个。出现 WORKSPACE_OPERATION_BUSY 时等待当前进程完成;异常退出时先确认锁中进程已经退出,再移除提示中的锁文件。锁只保护工具执行,不阻止编辑器修改源码;检查和部署期间应暂停其他写入。平台部署状态仍以 status/logs 为准。
@@ -20,6 +20,18 @@
20
20
 
21
21
  ## 更新项目 {#upgrade}
22
22
 
23
+ 按实际启用的功能核对要求,不把浏览器文案、局部错误提示等更新当成平台升级理由:
24
+
25
+ | 变化 | 平台条件 | 应用验证 |
26
+ | --- | --- | --- |
27
+ | ResourceTypes 和 Nest 类型绑定 | 复用现有 Data API;不新增服务端模型协议 | 运行生成与类型检查,确认隐藏字段可缺失及 revision 来源 |
28
+ | 浏览器安全诊断、安装错误提示 | 复用现有响应及请求头 | 模拟只读失败、导出失败、网络中断,确认没有重复写入 |
29
+ | 原流程提交结果恢复 | 可选 `business-process.original-resolution` 1.0.0 | 原幂等键查询、刷新恢复、授权拒绝,未知不能转换为未提交 |
30
+ | 业务角色候选 | 可选 `directory.assignment-candidates` 1.0.0 | 当前动作声明的角色、目标环境、过期/锁定账号、提交再校验 |
31
+ | 预检一次汇总 | 已协商的 configuration-compatibility 与共享 validator 摘要一致 | 同时缺能力/密钥/登录提供方时一次报告;成功结果仍按闭合协议校验 |
32
+
33
+ 平台能力声明、共享校验摘要、根包精确依赖及发布说明共同构成兼容依据。版本号大小、某次 Pod Ready 或历史工单“已发布”不能替代当前目标能力读回。未启用新增可选能力的旧应用继续使用原协议;不承诺未经回归验证的任意旧版本组合。
34
+
23
35
  更新项目的精确根包依赖并安装,提交相应锁文件;不要使用 latest、alpha 或范围版本代替明确版本。运行统一 check,处理实际契约变化,再在测试环境验证后晋级。
24
36
 
25
37
  执行 `pnpm openxiangda skill install --workspace . --force`,通过新版本根包安装 Skill;已有项目使用项目安装模式时会刷新 AGENTS 的平台管理段,并保留管理段外的自定义说明。没有可识别管理段的旧 AGENTS 不会被整份替换;先审阅工具输出的候选内容,再合并需要的规则。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "2.25.3",
3
+ "version": "2.26.0",
4
4
  "description": "OpenXiangda 2.0 的统一命令、应用 SDK、MCP 与中文 AI 技能资料。",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -60,13 +60,13 @@
60
60
  "antd-mobile": "5.42.3",
61
61
  "dayjs": "1.11.18",
62
62
  "docx-preview": "0.3.7",
63
- "openxiangda-cli": "2.5.19",
64
- "openxiangda-contracts": "2.21.0",
65
- "openxiangda-devkit-core": "2.23.0",
63
+ "openxiangda-cli": "2.5.20",
64
+ "openxiangda-contracts": "2.22.0",
65
+ "openxiangda-devkit-core": "2.24.0",
66
66
  "openxiangda-legacy": "npm:openxiangda@1.0.269",
67
- "openxiangda-mcp": "2.0.43",
68
- "openxiangda-nest": "2.5.4",
69
- "openxiangda-skill-kit": "2.3.17",
67
+ "openxiangda-mcp": "2.0.44",
68
+ "openxiangda-nest": "2.6.0",
69
+ "openxiangda-skill-kit": "2.3.18",
70
70
  "xlsx": "https://github.com/1377385356/openxiangda/releases/download/vendor-mirror/xlsx-0.20.3.tgz"
71
71
  },
72
72
  "peerDependencies": {
@@ -132,35 +132,44 @@
132
132
  },
133
133
  "openxiangdaRelease": {
134
134
  "schemaVersion": "openxiangda.release-notes/v1",
135
- "version": "2.25.3",
135
+ "version": "2.26.0",
136
136
  "status": "reviewed",
137
- "title": "OpenXiangda 2.25.3:浏览器跨标签身份重核",
138
- "summary": "应用标签重新获得焦点时,先读取平台当前身份与权限,避免旧页面继续展示原账号的功能。",
139
- "newFeatures": [],
137
+ "title": "OpenXiangda 2.26.0:原操作恢复、目标预检与类型化资源",
138
+ "summary": "保留未知提交的原操作,提前汇总目标环境缺项,提供类型化资源、受限角色候选和可复制的安全请求诊断。",
139
+ "newFeatures": [
140
+ "标准 PC/移动审批提交在响应未知时保留原操作定位信息,刷新后读取原回执;同一页面可按原键和冻结输入显式恢复,避免生成新键重复提交。",
141
+ "生成 ResourceTypes 并为 Nest 当前用户、业务动作和事件上下文提供资源绑定,约束资源名、字段、引用和更新 revision。",
142
+ "受信业务动作可读取声明角色的最小候选信息,服务端限定租户、环境、角色和有效期,提交时仍重新授权。"
143
+ ],
140
144
  "fixes": [
141
- "返回应用标签时重核当前授权;主体或权限作用域变化时停用旧页面,显示明确提示并要求用户确认后进入新身份。",
142
- "同身份重核保留未保存表单,重核失败或退出广播发生时不继续使用旧授权。"
145
+ "check/deploy 在构建前集中输出目标能力与配置缺项,附实际目标、版本、观测时间和 requestId;诊断信息不会混入封闭的平台响应契约。",
146
+ "新建应用和可选后端依赖安装失败保留安全错误分类与恢复提示,安装有界且不回显 registry 凭据。",
147
+ "浏览器请求、导出与授权刷新统一保留安全请求定位信息;网络写入结果未知时不自动重放。"
143
148
  ],
144
149
  "affectedUsers": [
145
- "使用 OpenXiangda 2.0 浏览器运行时的应用,尤其是同一浏览器中切换登录账号或权限发生变化的用户。"
150
+ "使用 OpenXiangda 2.0 开发、交付或运行标准业务审批的应用。",
151
+ "需要类型化 Native 资源绑定及业务角色候选的受管 Nest 扩展。"
146
152
  ],
147
153
  "upgradeSteps": [
148
- "应用更新到 openxiangda@2.25.3 后重新构建发布;CLI 对应版本为 openxiangda-cli@2.5.19。",
149
- "在预发环境以具名管理员和经办人双向切换标签,核对旧页面停用、未保存表单保护及当前角色能力。"
154
+ "应用固定 openxiangda@2.26.0,更新锁文件,重新生成契约并运行适用的 check/test。CLI 配套版本为 openxiangda-cli@2.5.20。",
155
+ "先读取目标环境能力。启用原流程回执恢复需要 business-process.original-resolution@1.0.0;角色候选需要 directory.assignment-candidates@1.0.0。缺少能力时先升级目标服务端,不猜测接口。",
156
+ "预发验证提交响应丢失、刷新后原键查询、已撤销权限拒绝,以及业务实际用到的资源与角色。复用同一已验收候选晋级。"
150
157
  ],
151
158
  "knownLimitations": [
152
- "重核在标签重新获得焦点或变为可见时触发;停留在前台的其他标签登录变更不会主动推送到当前页面。",
153
- "应用预发部署与具名角色验收需单独记录。"
159
+ "未观察到原命令不证明事务回滚;恢复界面保留原键。刷新后不持久保存业务表单内容,也不自动重放未知写入。",
160
+ "请求定位信息本身不授予读取后台日志或其他用户操作的权限。",
161
+ "类型、诊断和本地工具改进不要求无关平台升级;新增服务端协议需目标明确公布对应能力。",
162
+ "npm 发行验证不代替客户部署、真实角色或外部通知、签署和文件的业务验收。"
154
163
  ],
155
164
  "issues": [],
156
165
  "compatibility": {
157
166
  "node": ">=24",
158
167
  "workspaceGenerations": "v2",
159
- "platform": "使用现有 authz/current API,无需服务端升级",
160
- "v1": "独立 V1 不受影响。"
168
+ "platform": "保留现有平台基础协议;原流程恢复与受限角色候选按能力协商,分别需要 business-process.original-resolution@1.0.0 和 directory.assignment-candidates@1.0.0。",
169
+ "v1": "独立 V1 引擎与工作区不受影响。"
161
170
  },
162
- "sha256": "9dde692d0419326b98aa15648a78af7538668fd18cd516b0fcd3fdf3f4908249",
163
- "url": "https://github.com/1377385356/openxiangda/releases/tag/v2.25.3"
171
+ "sha256": "a26725320f8477e8829fc0b22e50b67e4f54da7978c9b5972924f954fbb7891f",
172
+ "url": "https://github.com/1377385356/openxiangda/releases/tag/v2.26.0"
164
173
  },
165
174
  "scripts": {
166
175
  "build": "node ../../scripts/prune-package-dist.mjs && tsc -p tsconfig.json && node scripts/copy-assets.mjs",
@@ -0,0 +1,41 @@
1
+ {
2
+ "schemaVersion": "openxiangda.release-notes/v1",
3
+ "version": "2.26.0",
4
+ "status": "reviewed",
5
+ "title": "OpenXiangda 2.26.0:原操作恢复、目标预检与类型化资源",
6
+ "summary": "保留未知提交的原操作,提前汇总目标环境缺项,提供类型化资源、受限角色候选和可复制的安全请求诊断。",
7
+ "newFeatures": [
8
+ "标准 PC/移动审批提交在响应未知时保留原操作定位信息,刷新后读取原回执;同一页面可按原键和冻结输入显式恢复,避免生成新键重复提交。",
9
+ "生成 ResourceTypes 并为 Nest 当前用户、业务动作和事件上下文提供资源绑定,约束资源名、字段、引用和更新 revision。",
10
+ "受信业务动作可读取声明角色的最小候选信息,服务端限定租户、环境、角色和有效期,提交时仍重新授权。"
11
+ ],
12
+ "fixes": [
13
+ "check/deploy 在构建前集中输出目标能力与配置缺项,附实际目标、版本、观测时间和 requestId;诊断信息不会混入封闭的平台响应契约。",
14
+ "新建应用和可选后端依赖安装失败保留安全错误分类与恢复提示,安装有界且不回显 registry 凭据。",
15
+ "浏览器请求、导出与授权刷新统一保留安全请求定位信息;网络写入结果未知时不自动重放。"
16
+ ],
17
+ "affectedUsers": [
18
+ "使用 OpenXiangda 2.0 开发、交付或运行标准业务审批的应用。",
19
+ "需要类型化 Native 资源绑定及业务角色候选的受管 Nest 扩展。"
20
+ ],
21
+ "upgradeSteps": [
22
+ "应用固定 openxiangda@2.26.0,更新锁文件,重新生成契约并运行适用的 check/test。CLI 配套版本为 openxiangda-cli@2.5.20。",
23
+ "先读取目标环境能力。启用原流程回执恢复需要 business-process.original-resolution@1.0.0;角色候选需要 directory.assignment-candidates@1.0.0。缺少能力时先升级目标服务端,不猜测接口。",
24
+ "预发验证提交响应丢失、刷新后原键查询、已撤销权限拒绝,以及业务实际用到的资源与角色。复用同一已验收候选晋级。"
25
+ ],
26
+ "knownLimitations": [
27
+ "未观察到原命令不证明事务回滚;恢复界面保留原键。刷新后不持久保存业务表单内容,也不自动重放未知写入。",
28
+ "请求定位信息本身不授予读取后台日志或其他用户操作的权限。",
29
+ "类型、诊断和本地工具改进不要求无关平台升级;新增服务端协议需目标明确公布对应能力。",
30
+ "npm 发行验证不代替客户部署、真实角色或外部通知、签署和文件的业务验收。"
31
+ ],
32
+ "issues": [],
33
+ "compatibility": {
34
+ "node": ">=24",
35
+ "workspaceGenerations": "v2",
36
+ "platform": "保留现有平台基础协议;原流程恢复与受限角色候选按能力协商,分别需要 business-process.original-resolution@1.0.0 和 directory.assignment-candidates@1.0.0。",
37
+ "v1": "独立 V1 引擎与工作区不受影响。"
38
+ },
39
+ "sha256": "a26725320f8477e8829fc0b22e50b67e4f54da7978c9b5972924f954fbb7891f",
40
+ "url": "https://github.com/1377385356/openxiangda/releases/tag/v2.26.0"
41
+ }
@@ -4,7 +4,7 @@
4
4
  {
5
5
  "name": "openxiangda-v2",
6
6
  "description": "使用 OpenXiangda 2.0 从模糊业务想法、已有资料或具体变更出发,通过对话发现模块、完成详细产品设计,由当前 AI Agent 按需用 Image 2.5 等图片能力形成视觉参考,直接实现真实页面并在浏览器修正,再检查和交付应用;维护 1.x 应用时使用对应的 1.x 技能。",
7
- "sha256": "f9c3e96e4a57a0bb2f44466273244d6303729716f78674eca32ce76d88e71fa2"
7
+ "sha256": "b6c20b95ccba092404141520790431ecf6c2162a85843e32798c63b5713558d5"
8
8
  }
9
9
  ]
10
10
  }
@@ -40,10 +40,10 @@ AI 接到新应用、页面或改版任务时,在同一个 OpenXiangda 工作
40
40
  未创建工作区时使用本 Skill 随根包发布的精确版本:
41
41
 
42
42
  ```bash
43
- pnpm dlx openxiangda@2.25.3 auth status --cwd <应用目录> --base-url <平台地址> --json
44
- pnpm dlx openxiangda@2.25.3 login --cwd <应用目录> --base-url <平台地址>
45
- pnpm dlx openxiangda@2.25.3 create <应用目录> --base-url <同一平台地址>
46
- pnpm dlx openxiangda@2.25.3 skill install --force
43
+ pnpm dlx openxiangda@2.26.0 auth status --cwd <应用目录> --base-url <平台地址> --json
44
+ pnpm dlx openxiangda@2.26.0 login --cwd <应用目录> --base-url <平台地址>
45
+ pnpm dlx openxiangda@2.26.0 create <应用目录> --base-url <同一平台地址>
46
+ pnpm dlx openxiangda@2.26.0 skill install --force
47
47
  ```
48
48
 
49
49
  创建前把产品要求的目标平台明确带入命令,不从旧登录态推断站点。已有工作区从原绑定恢复,平台不一致时先解决登录与目标,不改 link 文件跨站创建。
@@ -41,6 +41,15 @@ SDK 继承当前环境与身份,平台沿用发起人或既有超级管理员
41
41
  `items/nextCursor`,分页与多次流程的选择规则见[前端](frontend.md)。找回后使用原
42
42
  `receipt/poll/surface`;查询不重放提交、不生成第二份命令状态。
43
43
 
44
+ 连 commandId 都没收到时,用同一动作的 `businessProcess.resolveOriginal({ workflowCode,
45
+ idempotencyKey })` 查询原操作。此能力需要 `business-process.original-resolution` 1.0.0。
46
+ `committed` 才有可信回执;`not_observed` 可能仍在提交,不能据此生成新键或宣称回滚。
47
+ 前端可用 `resolveBusinessProcessOriginal`(`openxiangda/react`),传原 workflowCode、
48
+ operationCode、idempotencyKey;SDK 绑定当前环境并核验返回关联。Named Action 如果业务无需
49
+ 审批,没有流程回执并不代表业务没写入,应沿该动作自身回执诊断。
50
+ 标准 PC/移动发起页在响应未知时保留原操作定位信息,刷新可继续查询;同一页面、原身份和
51
+ 版本内可手动重试冻结的标准输入,绝不自动重发或悄悄换键。
52
+
44
53
  自定义表单页若先用 `createResourceFormDraftClient` 保存认证草稿,并由 Named Action
45
54
  提交业务记录和流程,则在同一次 `OpenXiangdaBusinessProcessService.commit` 中传入
46
55
  `formDraft: { resourceCode, id, expectedRevision, mode, recordId?, viewCode? }`。草稿必须
@@ -101,21 +110,28 @@ data: {
101
110
 
102
111
  ### 幂等冲突复核 {#idempotency-recovery}
103
112
 
104
- 同一 `idempotencyKey` 要求内容指纹一致。update 事务携带 `expectedRevision`,重试时 revision 已前进会触发 409 `OPENXIANGDA_NATIVE_DATA_IDEMPOTENCY_CONFLICT`。捕获后回读当前状态确认效果已生效,按幂等结果返回;不要换新键重试:
113
+ 同一 `idempotencyKey` 要求内容指纹一致。冻结首次请求的 operations、guards、expectedRevision、主体、环境和版本上下文;重试不能重新计算这些值。平台原回执的 `replayed` 才是重放成功证据。业务记录已经变化,本身不会导致原请求的幂等内容冲突;重新读取 revision 并改变请求才会。
114
+
115
+ `isIdempotencyConflict(error)` 只识别 409 `OPENXIANGDA_NATIVE_DATA_IDEMPOTENCY_CONFLICT`,不证明首次请求已成功。保留原操作并核对原回执;结果不明时显示“结果待确认”,不能把当前记录状态拼成伪造的成功回执,也不能换新键重试。部署 Head 改变时先恢复原上下文,不把同一键发送到另一版本当作原请求恢复。
116
+
117
+ ### 使用生成类型绑定资源 {#typed-resources}
118
+
119
+ 工具生成的共享契约导出 `ResourceTypes`;使用项目锁定版本的 `pnpm openxiangda check` 验证接入。三种 Nest 数据服务均保留原主体;当前用户业务优先用当前用户服务,具名业务动作使用业务服务。
105
120
 
106
121
  ```ts
107
- import { isIdempotencyConflict } from 'openxiangda/nest';
108
-
109
- try {
110
- result = await this.data.transaction(idempotentTransaction(key, operations, guards));
111
- } catch (error) {
112
- if (isIdempotencyConflict(error) && alreadyApplied(await this.data.get(...))) {
113
- return { idempotencyKey: key, replayed: true, ...currentState };
114
- }
115
- throw error;
116
- }
122
+ import type { ResourceTypes } from '@app/contracts';
123
+
124
+ const resources = this.data.resources<ResourceTypes>();
125
+ const requests = resources('repair-requests');
126
+ const record = await requests.get(input.id);
127
+ return requests.update(record.data.id, {
128
+ expectedRevision: record.data.revision,
129
+ data: { assignedTechnician: userSnapshot(input.technicianId) },
130
+ });
117
131
  ```
118
132
 
133
+ 资源名、写入字段、引用形状和 query 的字段/排序键会在 TypeScript 检查时验证;示例字段须由自己的模型声明。get/create/update/delete 保留 `data` 信封,revision 位于 `record.data.revision`。query 返回分页的 `items`。字段权限可能隐藏业务字段,所以读取类型保留这些字段可缺失的事实;应用必须按权限和必需字段做有意义的提示。该包装不会自动重试、修改 revision 或提升权限。运行时仍由平台校验所有输入。
134
+
119
135
  事务守卫的 `errorCode` 必须匹配 `^OPENXIANGDA_[A-Z0-9_]{1,96}$`,例如 `OPENXIANGDA_REPAIR_REQUEST_NOT_PENDING`。
120
136
 
121
137
  ## 在同一事务中引用前序 create 生成的 id {#transaction-references}
@@ -161,8 +177,21 @@ platformAccess: { roleAssertions: { roleCodes: ['technician'] } }
161
177
  ```
162
178
 
163
179
  `technician` 必须存在于本应用 `authz.roles`,最多声明 20 个角色。应用管理员身份
164
- 不自动代表维修角色。人员候选可以使用已有且已委托管理范围的成员查询;这项声明
165
- 本身不授予成员管理或人员目录权限。
180
+ 不自动代表维修角色。经办人使用请求作用域 `OpenXiangdaBusinessDirectoryService` 查询
181
+ 本动作声明的候选,无需成员管理权:
182
+
183
+ ```ts
184
+ const page = await businessDirectory.assignmentCandidates({
185
+ roleCode: 'technician', keyword: input.keyword, limit: 20,
186
+ ...(input.cursor ? { cursor: input.cursor } : {}),
187
+ });
188
+ // page.items 仅有 value/label;下一页沿用同一关键词和 page.nextCursor。
189
+ ```
190
+
191
+ 这项可选能力需要目标平台 `directory.assignment-candidates` 1.0.0。环境由 SDK 绑定,
192
+ 禁止传入任意环境或账号。平台只返回生效、未过期、正常且未锁定的成员,验证账号与正式
193
+ 账号隔离。游标绑定环境 Head、调用者、动作和角色,收到上下文变化错误后清空游标重新查询。
194
+ 候选结果只用于选人;提交时仍使用下面的事务条件,不能凭查询结果绕过重新核验。
166
195
 
167
196
  在 `OpenXiangdaBusinessDataApiService` 的同一次事务中表达业务状态与目标角色:
168
197
 
@@ -68,10 +68,10 @@ MCP 服务随项目根包一起安装,AI 客户端的 stdio 连接仍需配置
68
68
  以下命令的版本占位符由随包资料替换为该根包的精确版本。网站源码阅读者应先确认要使用的发行版本。
69
69
 
70
70
  ```bash
71
- pnpm dlx openxiangda@2.25.3 skill install --force
72
- pnpm dlx openxiangda@2.25.3 auth status --base-url <平台地址> --json
73
- pnpm dlx openxiangda@2.25.3 login --cwd my-app --base-url https://platform.example.com
74
- pnpm dlx openxiangda@2.25.3 create my-app --base-url https://platform.example.com
71
+ pnpm dlx openxiangda@2.26.0 skill install --force
72
+ pnpm dlx openxiangda@2.26.0 auth status --base-url <平台地址> --json
73
+ pnpm dlx openxiangda@2.26.0 login --cwd my-app --base-url https://platform.example.com
74
+ pnpm dlx openxiangda@2.26.0 create my-app --base-url https://platform.example.com
75
75
  cd my-app
76
76
  pnpm openxiangda context --json
77
77
  pnpm openxiangda dev
@@ -174,9 +174,9 @@ MCP 的 `docs_read` 可以读取本说明,当前没有独立的源码操作 MC
174
174
  无需本地工作区,使用本 Skill 随包精确版本或已安装的对应 CLI:
175
175
 
176
176
  ```bash
177
- pnpm dlx openxiangda@2.25.3 auth status --base-url <平台> --json
178
- pnpm dlx openxiangda@2.25.3 source resolve <仓库URL> --base-url <平台> --json
179
- pnpm dlx openxiangda@2.25.3 source clone <仓库URL> <新目录> --base-url <平台> --json
177
+ pnpm dlx openxiangda@2.26.0 auth status --base-url <平台> --json
178
+ pnpm dlx openxiangda@2.26.0 source resolve <仓库URL> --base-url <平台> --json
179
+ pnpm dlx openxiangda@2.26.0 source clone <仓库URL> <新目录> --base-url <平台> --json
180
180
  ```
181
181
 
182
182
  登录缺失或站点不匹配时,先按该平台执行 login。resolve 根据平台已经登记的绑定返回
@@ -64,6 +64,21 @@ pnpm openxiangda accept --plan .openxiangda/acceptance-plan.json --json
64
64
 
65
65
  记录源码/包版本、AppVersion、环境、角色、预期及实际结果、必要请求标识。区分本地检查、分发安装、部署激活与业务验收。某项未执行时说明原因,不将其写成通过。
66
66
 
67
+ ## 复制请求诊断 {#request-diagnostics}
68
+
69
+ 标准浏览器请求错误保留服务端 requestId,文件导出及权限读取重试耗尽也使用同一错误类型。自定义页面通过公开入口读取固定格式诊断:
70
+
71
+ ```ts
72
+ import { platformRequestDiagnostic } from 'openxiangda/react';
73
+
74
+ function supportDetails(error: unknown) {
75
+ const diagnostic = platformRequestDiagnostic(error);
76
+ return diagnostic ? JSON.stringify(diagnostic, null, 2) : null;
77
+ }
78
+ ```
79
+
80
+ 将这段结果放入当前操作的错误详情,附应用版本和原 operationId/DeploymentRun;不要复制 Cookie、令牌、完整请求正文或原始响应。诊断包含错误码、请求路径(无 query)、方法、站点内应用/环境、观测时间和合法 requestId。网络未收到响应时 requestId 为 null,不能编造关联标识。该信息不等于提交结果:写入未知时查询原操作,保留原键与原输入;不要自动换键再写。Nest SDK 的平台错误已有 `request` 上下文,平台管理仍通过授权范围内的日志/支持通道检索。
81
+
67
82
  ## 并发执行
68
83
 
69
84
  同一工作区的公共 check 和测试 deploy 共享本地互斥锁,前一个命令结束后才能启动下一个。出现 WORKSPACE_OPERATION_BUSY 时等待当前进程完成;异常退出时先确认锁中进程已经退出,再移除提示中的锁文件。锁只保护工具执行,不阻止编辑器修改源码;检查和部署期间应暂停其他写入。平台部署状态仍以 status/logs 为准。
@@ -20,6 +20,18 @@
20
20
 
21
21
  ## 更新项目 {#upgrade}
22
22
 
23
+ 按实际启用的功能核对要求,不把浏览器文案、局部错误提示等更新当成平台升级理由:
24
+
25
+ | 变化 | 平台条件 | 应用验证 |
26
+ | --- | --- | --- |
27
+ | ResourceTypes 和 Nest 类型绑定 | 复用现有 Data API;不新增服务端模型协议 | 运行生成与类型检查,确认隐藏字段可缺失及 revision 来源 |
28
+ | 浏览器安全诊断、安装错误提示 | 复用现有响应及请求头 | 模拟只读失败、导出失败、网络中断,确认没有重复写入 |
29
+ | 原流程提交结果恢复 | 可选 `business-process.original-resolution` 1.0.0 | 原幂等键查询、刷新恢复、授权拒绝,未知不能转换为未提交 |
30
+ | 业务角色候选 | 可选 `directory.assignment-candidates` 1.0.0 | 当前动作声明的角色、目标环境、过期/锁定账号、提交再校验 |
31
+ | 预检一次汇总 | 已协商的 configuration-compatibility 与共享 validator 摘要一致 | 同时缺能力/密钥/登录提供方时一次报告;成功结果仍按闭合协议校验 |
32
+
33
+ 平台能力声明、共享校验摘要、根包精确依赖及发布说明共同构成兼容依据。版本号大小、某次 Pod Ready 或历史工单“已发布”不能替代当前目标能力读回。未启用新增可选能力的旧应用继续使用原协议;不承诺未经回归验证的任意旧版本组合。
34
+
23
35
  更新项目的精确根包依赖并安装,提交相应锁文件;不要使用 latest、alpha 或范围版本代替明确版本。运行统一 check,处理实际契约变化,再在测试环境验证后晋级。
24
36
 
25
37
  执行 `pnpm openxiangda skill install --workspace . --force`,通过新版本根包安装 Skill;已有项目使用项目安装模式时会刷新 AGENTS 的平台管理段,并保留管理段外的自定义说明。没有可识别管理段的旧 AGENTS 不会被整份替换;先审阅工具输出的候选内容,再合并需要的规则。