openxiangda-skill-kit 2.0.0-alpha.91 → 2.0.0-alpha.94
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 +9 -1
- package/skills/openxiangda-v2/references/backend.md +4 -0
- package/skills/openxiangda-v2/references/data-authz.md +44 -0
- package/skills/openxiangda-v2/references/frontend.md +45 -12
- package/skills/openxiangda-v2/references/workflow-events.md +78 -0
- package/skills/openxiangda-v2/references/workspace.md +4 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openxiangda-skill-kit",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.94",
|
|
4
4
|
"description": "Validation and deterministic packaging for OpenXiangda 2.0 AI skills.",
|
|
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.0.0-alpha.
|
|
20
|
+
"openxiangda-devkit-core": "2.0.0-alpha.75"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
23
23
|
"tsx": "4.23.12",
|
|
@@ -38,10 +38,18 @@ For an AI-native client, start the workspace protocol through the same pinned ex
|
|
|
38
38
|
pnpm exec openxiangda --mcp-stdio --cwd <workspace>
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
Read `openxiangda://workspace/contracts` or call `contract_describe`. When AppSpec is enabled, read `openxiangda://workspace/appspec` or call `appspec_context`; treat it as advisory context, never as deployment authority. Require `aiCatalog` and `aiCatalogDigest` to match the normal compiler output. Never create an application MCP server, Catalog file, preview store or AI authorization path.
|
|
41
|
+
Read `openxiangda://workspace/contracts` or call `contract_describe`. For first-time menu authoring, copy `data.adminNavigationAuthoring.suggestion.expression` once into `frontend.admin.navigation` with its listed `openxiangda/config` imports, then edit that application-owned declaration; never treat the proposal as runtime discovery. When AppSpec is enabled, read `openxiangda://workspace/appspec` or call `appspec_context`; treat it as advisory context, never as deployment authority. Require `aiCatalog` and `aiCatalogDigest` to match the normal compiler output. Never create an application MCP server, Catalog file, preview store or AI authorization path.
|
|
42
42
|
|
|
43
43
|
The browser uses the current logged-in user's complete application-role union. The platform is authoritative for capabilities, fields, rows and RLS. A declared Perspective is only a read projection over that union: it may narrow pages, rows and readable fields, but never create/update/delete, workflow or custom-action authorization. Omitted Perspective means the complete union. Application code does not replace the authenticated identity, persist a platform token, construct an authorization result or keep a second permission state.
|
|
44
44
|
|
|
45
|
+
Applications own one explicit typed admin navigation declaration. The compiler
|
|
46
|
+
owns page/route generation, but it never turns every generated resource or
|
|
47
|
+
Workflow into a menu item; the Shell renders only declared navigation and then
|
|
48
|
+
filters it by authorization. Keep page existence, route reachability and menu
|
|
49
|
+
visibility separate. Use resource mutation ownership and per-operation
|
|
50
|
+
generated surface flags, and give only self-contained `standalone` Workflow
|
|
51
|
+
launch pages a menu entry.
|
|
52
|
+
|
|
45
53
|
Read only the references needed for the current change, except the mandatory discovery and Data/authorization rules above:
|
|
46
54
|
|
|
47
55
|
- [Discovery](references/discovery.md)
|
|
@@ -243,6 +243,10 @@ contract:
|
|
|
243
243
|
and may protect a mutation of another resource;
|
|
244
244
|
- `record-assert` locks one exact record and checks declared field values or
|
|
245
245
|
declared field-to-field comparisons;
|
|
246
|
+
- `databaseNowAssertion('publishAt', 'lte')` compares a declared `datetime`
|
|
247
|
+
field with the single PostgreSQL transaction time. Do not pass `Date.now()`,
|
|
248
|
+
an offset, a SQL function or a fallback timestamp; a successful idempotent
|
|
249
|
+
replay returns the original `evaluatedAt` without re-evaluating the guard;
|
|
246
250
|
- `increment` targets one declared integer field and must have a matching
|
|
247
251
|
same-resource, same-record `record-assert` guard;
|
|
248
252
|
- never send SQL, table names, expressions, old guards without `errorCode`, or
|
|
@@ -62,6 +62,16 @@ also granted only to the intended roles. They are owned and exported by the
|
|
|
62
62
|
generated field policy, so do not repeat them in `authz.capabilities`.
|
|
63
63
|
`authz.capabilities` contains only explicit `backend` or `ui` capabilities.
|
|
64
64
|
|
|
65
|
+
Declare mutation ownership on the same resource with
|
|
66
|
+
`mutationOwner: 'native' | 'action' | 'readonly' | 'workflow'`. Native defaults
|
|
67
|
+
to generated list/detail/create/update/delete. Other owners default to readable
|
|
68
|
+
list/detail only and must use their named action or Workflow boundary for
|
|
69
|
+
mutation. Use `generated: { list, detail, create, update, delete }` to narrow
|
|
70
|
+
the generated page/operation surface. The compiler rejects Native mutation
|
|
71
|
+
pages, AI operations or role grants on a non-Native owner, and rejects
|
|
72
|
+
create/update when no writable business field exists. Do not grant a resource
|
|
73
|
+
create/update/delete capability to make an action-owned record editable.
|
|
74
|
+
|
|
65
75
|
Declare optional work Perspectives once at the application root. A Perspective
|
|
66
76
|
references existing role codes; the compiler derives its readable capability
|
|
67
77
|
projection, so never hand-author `capabilityCodes` or duplicate row filters:
|
|
@@ -99,6 +109,40 @@ generated UI and platform field policies.
|
|
|
99
109
|
|
|
100
110
|
Field types are semantic, not PostgreSQL storage aliases. Use the catalog in the generated `AGENTS.md`: for example `text.short`, `number.integer`, `user.single`, `department.multiple`, `resource-ref.single`, `file`, `address` and `subtable`. The compiler alone chooses storage columns and constraints. Reference fields store JSON display values. For `resource-ref.*`, `resourceCode`, `value`, `label`, optional `description` and optional `snapshot` are convenient historical display data only: the target resource remains authoritative, the platform does not create a foreign key or refresh/check the stored JSON, and business actions that need current target state must query it by `resourceCode` plus `value`. A resource source `labelField` must point to `text.short` or `text.long`; a `serial-number` field can be listed in `searchFields`, `descriptionFields` or `snapshotFields`, but it is not a display label. File limits exist only under `file`; `maxCount` owns the single/multiple bound and `maxSizeMb` owns the per-file size bound. There is no `file.multiple` key.
|
|
101
111
|
|
|
112
|
+
Numeric bounds belong on the field declaration and are enforced by the
|
|
113
|
+
platform for every write path. They are inclusive, and only valid on
|
|
114
|
+
`number.integer` or `number.decimal`:
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
{ code: 'capacity', type: 'number.integer', label: '容量', required: true, min: 0, max: 10000 }
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Cross-field rules belong on the resource, not in a generated form callback.
|
|
121
|
+
Only bounded same-record field comparisons are supported; declare multiple
|
|
122
|
+
invariants when all must hold:
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
{
|
|
126
|
+
code: 'sessions',
|
|
127
|
+
name: '场次',
|
|
128
|
+
fields: [
|
|
129
|
+
{ code: 'startAt', type: 'datetime', label: '开始时间', required: true },
|
|
130
|
+
{ code: 'endAt', type: 'datetime', label: '结束时间', required: true },
|
|
131
|
+
{ code: 'capacity', type: 'number.integer', label: '容量', required: true, min: 0 },
|
|
132
|
+
{ code: 'occupied', type: 'number.integer', label: '已占用', required: true, min: 0 },
|
|
133
|
+
],
|
|
134
|
+
invariants: [
|
|
135
|
+
{ code: 'time-order', expression: { leftField: 'startAt', operator: 'lt', rightField: 'endAt' } },
|
|
136
|
+
{ code: 'capacity-not-exceeded', expression: { leftField: 'capacity', operator: 'gte', rightField: 'occupied' } },
|
|
137
|
+
],
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
`datetime-range` is always a non-empty half-open interval `[start, end)`.
|
|
142
|
+
Adjacent values such as `[10:00, 11:00)` and `[11:00, 12:00)` do not overlap.
|
|
143
|
+
Use the ordinary `overlaps` query operator or a `query-empty` transaction guard;
|
|
144
|
+
never add or subtract milliseconds at the boundary.
|
|
145
|
+
|
|
102
146
|
Do not author raw schema or storage words as field types. `string`, `text`,
|
|
103
147
|
`integer`, `decimal`, `boolean`, `date`, `datetime`, `uuid`, `json` and `file`
|
|
104
148
|
describe value or storage families only when the platform protocol says so;
|
|
@@ -28,21 +28,54 @@ union. Never fetch identity for the header, display role codes, add a second
|
|
|
28
28
|
identity selector, or copy Shell and
|
|
29
29
|
directory-client implementations into application source.
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
`
|
|
33
|
-
|
|
34
|
-
`
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
31
|
+
The application owns the editable admin information architecture through the
|
|
32
|
+
typed `defineAdminNavigation`, `adminNavigationGroup`, `adminResourcePage`,
|
|
33
|
+
`adminOperationPage`, `adminWorkflowWorkCenterPage` and
|
|
34
|
+
`adminWorkflowLaunchPage` helpers in `openxiangda/config`. The compiler emits
|
|
35
|
+
all reachable `adminPages`, but the Shell renders only pages explicitly
|
|
36
|
+
referenced by generated `adminNavigation`, then applies current-user access as
|
|
37
|
+
a final filter. Page existence, route reachability and menu visibility are
|
|
38
|
+
separate: detail/new/edit/dynamic/handoff pages never become menu entries by
|
|
39
|
+
discovery, and permission logic cannot create entries. Read
|
|
40
|
+
`openxiangda://workspace/contracts` or call `contract_describe`, then copy
|
|
41
|
+
`data.adminNavigationAuthoring.suggestion.expression` once into
|
|
42
|
+
`frontend.admin.navigation` with the listed `openxiangda/config` imports. The
|
|
43
|
+
proposal is deterministic and editable; the compiler/runtime never invokes it
|
|
44
|
+
or appends newly added resources later.
|
|
45
|
+
|
|
46
|
+
Declare custom routes in `openxiangda.config.ts`, import the generated
|
|
47
|
+
`appRoutes`, and bind every route key to exactly one local React page with
|
|
48
|
+
`defineApplicationContributions` from `openxiangda/react`. Pass the result to
|
|
49
|
+
`OpenXiangdaApplication`. The runtime registers `surface: 'admin'` routes inside
|
|
50
|
+
the one platform Shell; do not wrap them in another Shell. It renders
|
|
51
|
+
`surface: 'user'` routes without the admin Shell so mobile/user experiences can
|
|
52
|
+
own their page layout without creating another router, identity provider or
|
|
53
|
+
permission store. Only static admin routes explicitly referenced by
|
|
54
|
+
`frontend.admin.navigation` enter the menu. Hidden routes retain the same
|
|
55
|
+
`capability` or `access.allOf/anyOf`, including ancestor constraints. Keep admin
|
|
56
|
+
operation pages under `/admin/operations`; parameterized routes remain
|
|
57
|
+
reachable but cannot be menu references. `defineAdminContributions` remains an
|
|
58
|
+
admin-only helper and intentionally rejects `user` routes.
|
|
59
|
+
|
|
60
|
+
This is also the whole-application composition contract: pass the resulting
|
|
61
|
+
`contributions` to `OpenXiangdaApplication` and let that component remain the
|
|
62
|
+
only owner of `BrowserRouter`, `RuntimeBoundary`, Refine, generated resource and
|
|
63
|
+
Workflow routes, and the admin Shell. A user page may render an independent PC
|
|
64
|
+
or mobile layout, but it must not add a nested router/Shell or copy generated
|
|
65
|
+
routes. Route parameters continue to come from React Router, and generated
|
|
66
|
+
capability plus ancestor access guards run before the component renders.
|
|
67
|
+
|
|
68
|
+
To expose the standard application-level todo center, add
|
|
69
|
+
`adminApplicationTodoCenterPage()` to an explicit admin navigation group. The
|
|
70
|
+
compiler generates `/admin/todos`; the same runtime exposes the independent
|
|
71
|
+
mobile `/m/todos` page. The page reads only the authenticated user's
|
|
72
|
+
Notification Hub recipient projection and deep-links to the platform-resolved
|
|
73
|
+
target. Do not query Notification Hub management endpoints or recreate a local
|
|
74
|
+
message state store.
|
|
42
75
|
|
|
43
76
|
For a small business action on a generated resource page, use the typed
|
|
44
77
|
`resources[resourceCode].toolbar`, `.row` or `.detail` slots accepted by
|
|
45
|
-
`
|
|
78
|
+
`defineApplicationContributions`. Declare a stable action code, label and
|
|
46
79
|
capability/access expression. The render context contains only the current
|
|
47
80
|
resource, already-authorized record or selection, and a bounded `refresh()`;
|
|
48
81
|
it does not own CRUD, revisions, fields or authorization. Invoke a guarded Nest
|
|
@@ -19,6 +19,20 @@ Use these optional modules only when the application has a real standard approva
|
|
|
19
19
|
|
|
20
20
|
Declare workflow topology and bindings once in `openxiangda.config.ts`. Use only approval, condition and end nodes for the standard module. Keep business data in Data API/App API and pass an immutable `dataRef`, business revision and bounded facts into prepare/start.
|
|
21
21
|
|
|
22
|
+
Every definition declares a launch mode: `standalone` for a self-contained
|
|
23
|
+
generated save-and-start page, `custom-page` for an application operation page,
|
|
24
|
+
`hidden-handoff` for a non-menu handoff route, or `work-center-only` when users
|
|
25
|
+
only act on existing tasks. Only `standalone` may be referenced by
|
|
26
|
+
`adminWorkflowLaunchPage`; the generated browser runtime uses the workflow's
|
|
27
|
+
localized definition title, so applications do not maintain code-to-title
|
|
28
|
+
maps. A standalone page receives all durable business context through its
|
|
29
|
+
typed save handler and URL/search contract; it must never depend on transient
|
|
30
|
+
router location state. Work center, task and instance pages remain reachable
|
|
31
|
+
without becoming launch menu entries. Bind the generated metadata with
|
|
32
|
+
`defineWorkflowLaunchContributions(workflowDefinitions, handlers)`; handlers
|
|
33
|
+
only persist the durable business revision, while generated code keeps title
|
|
34
|
+
and launch mode authoritative.
|
|
35
|
+
|
|
22
36
|
Use an assignee Provider only when resolution depends on application data. The Provider returns stable Native user/role subjects and never makes the final task authorization decision.
|
|
23
37
|
|
|
24
38
|
The standard operations are approve, reject, return, resubmit, transfer, delegate, add-sign, withdraw, admin reassign, admin terminate and reminder. Render only operations returned by the task/instance Surface. A template or application action cannot add a Workflow command that is absent from the Surface.
|
|
@@ -70,6 +84,70 @@ Use a canonical navigation target with `PLATFORM_ROUTE`, `APP_ROUTE` or allowlis
|
|
|
70
84
|
|
|
71
85
|
The Notification Hub resolves desktop, mobile and channel deep links. The landing page always re-runs platform authentication and Data/AuthZ/Workflow authorization.
|
|
72
86
|
|
|
87
|
+
To replace the standard Workflow detail page everywhere, declare both route
|
|
88
|
+
codes on the Workflow definition declaration. The desktop route must be an
|
|
89
|
+
`admin` route, the mobile route must be a `user` route, and both paths contain
|
|
90
|
+
exactly `:instanceId`:
|
|
91
|
+
|
|
92
|
+
```ts
|
|
93
|
+
frontend: {
|
|
94
|
+
root: 'apps/web',
|
|
95
|
+
routes: [
|
|
96
|
+
{
|
|
97
|
+
code: 'purchase-detail',
|
|
98
|
+
path: '/admin/operations/purchases/:instanceId',
|
|
99
|
+
label: '采购审批详情',
|
|
100
|
+
surface: 'admin',
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
code: 'purchase-detail-mobile',
|
|
104
|
+
path: '/m/purchases/:instanceId',
|
|
105
|
+
label: '移动采购审批详情',
|
|
106
|
+
surface: 'user',
|
|
107
|
+
},
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
workflows: {
|
|
111
|
+
definitions: [{
|
|
112
|
+
version: 1,
|
|
113
|
+
definition: purchaseApproval,
|
|
114
|
+
launch: { mode: 'work-center-only' },
|
|
115
|
+
detailRouteCode: {
|
|
116
|
+
desktop: 'purchase-detail',
|
|
117
|
+
mobile: 'purchase-detail-mobile',
|
|
118
|
+
},
|
|
119
|
+
}],
|
|
120
|
+
bindings: [],
|
|
121
|
+
activations: [],
|
|
122
|
+
},
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Bind the generated routes with `defineApplicationContributions`. Inside the
|
|
126
|
+
page, read `instanceId` from React Router and optional `taskId` from the query.
|
|
127
|
+
Use `loadWorkflowInstanceSurface`, `loadWorkflowTaskSurface` and
|
|
128
|
+
`loadWorkflowTimeline` from `openxiangda/core`; render only operations returned
|
|
129
|
+
by the Surface. The platform resolves the same declaration for desktop/mobile
|
|
130
|
+
work centers, Notification Hub logical messages, DingTalk cards and other
|
|
131
|
+
channel snapshots. Omitting `detailRouteCode` keeps the standard pages. A
|
|
132
|
+
declared but missing or incompatible route fails closed rather than falling
|
|
133
|
+
back silently.
|
|
134
|
+
|
|
135
|
+
Standard launch entry is also a platform Surface. Desktop uses
|
|
136
|
+
`/admin/workflows/:workflowCode/new` and mobile uses
|
|
137
|
+
`/m/workflows/:workflowCode/start`; both first load
|
|
138
|
+
`loadWorkflowLaunchSurface(workflowCode)`, then use the same durable
|
|
139
|
+
`saveBusinessRevision -> prepareWorkflowStart -> startWorkflow` protocol.
|
|
140
|
+
`custom-page` and `work-center-only` declarations do not expose the standard
|
|
141
|
+
launch Surface. After start, navigate through the device's standard instance
|
|
142
|
+
entry so the current `detailRouteCode` contract can redirect consistently.
|
|
143
|
+
|
|
144
|
+
An application-level inbox is enabled in explicit admin navigation with
|
|
145
|
+
`adminApplicationTodoCenterPage()`. It projects Notification Hub messages and
|
|
146
|
+
per-recipient interaction for the current logged-in user only; it is not the
|
|
147
|
+
Notification Hub management console. Use its `去处理` navigation to enter the
|
|
148
|
+
authorized Workflow or application page, and keep approve/reject/transfer
|
|
149
|
+
commands on the destination Surface.
|
|
150
|
+
|
|
73
151
|
## Interactive channel actions
|
|
74
152
|
|
|
75
153
|
Channel callbacks enter the Notification Action Gateway. The gateway verifies tenant, environment, recipient identity, task/participant, Surface revision, operation, nonce, signature and expiry before calling Workflow.
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
- Use only the workspace-pinned CLI: `pnpm openxiangda <command>`. Never invoke a bare global `openxiangda` inside a 2.0 task.
|
|
4
4
|
- `appspec/` is the optional OpenXiangda 2.0 business-intent layer. Before changing observable behavior, read the bounded index with `pnpm openxiangda spec context --json`, then select only the relevant stable ID; use no ChangeSpec for L0 work, one short ChangeSpec for L1, and add permission/rollback/concurrency detail only for L2/L3. Before close, the user—not AI—confirms `currentSpec=merged` or `not-applicable`. AppSpec is advisory and never a release gate. Never read, import or migrate 1.x `openspec/` or SDD.
|
|
5
5
|
- Use Vite, React Router, Refine Core and Ant Design. Do not add Umi, ProComponents or another admin shell.
|
|
6
|
-
-
|
|
7
|
-
- Declare each resource once in `openxiangda.config.ts` with only `code`, `name`, `fields` and optional list/layout/data-policy settings. Each field owns type, label, required state, Surface flags, reference/file metadata and access. Resource codes are lower kebab-case.
|
|
6
|
+
- Bind every generated `appRoutes` entry to its local page with `defineApplicationContributions`; desktop `admin` routes stay inside the platform Shell, while `user` routes render without an admin Shell for independent mobile/user experiences. Use only its typed `toolbar`, `row` and `detail` resource slots for generated resource actions. Declare the complete editable admin menu with `defineAdminNavigation` and its page/group helpers; the Shell renders only generated `adminNavigation` references and permissions only filter them. Do not create another router, menu store, layout, identity provider, permission store or copied CRUD page; route/action access uses capability or `allOf`/`anyOf`, while Data/App API and Workflow authorization remain server-owned.
|
|
7
|
+
- Declare each resource once in `openxiangda.config.ts` with only `code`, `name`, `fields` and optional `mutationOwner`, generated/list/layout/data-policy settings. Each field owns type, label, required state, Surface flags, reference/file metadata and access. Resource codes are lower kebab-case. Use `native` for direct Data API mutations, `action`, `readonly` or `workflow` for non-Native ownership; never grant or generate Native mutation for a non-Native owner.
|
|
8
8
|
- Never write resource-level `schemaVersion`, `appCode`, `schema`, `surface`, `capabilities`, `fieldPolicies` or `platform/data` modules. The compiler derives the strict DataResource, CRUD capabilities, Surface and AI Schema. The application manifest still starts with its one top-level `schemaVersion: 3`.
|
|
9
9
|
- Ordinary list/get/create/update/delete, filters, export and batch operations use the platform Native Data API. Do not create Function CRUD or NestJS wrappers.
|
|
10
10
|
- Add NestJS only for a named business action that needs a cross-resource transaction, an invariant or an external side effect.
|
|
@@ -20,6 +20,6 @@
|
|
|
20
20
|
- `option.*`, `user.*`, `department.*` and `resource-ref.*` values never collapse to scalar IDs. Single values store one labeled object and multiple values store object arrays. `resource-ref.*` JSON is not a foreign key, trusted target snapshot or automatically refreshed copy; current target state is read by `resourceCode` plus `value`. A resource source `labelField` must be `text.short` or `text.long`; `serial-number` is allowed in source search, description and snapshot fields, but not as the label. `location` accepts only exact WGS84 coordinates captured by DingTalk or browser geolocation; it has no manual input or `manual` source. Roles that consume directory-backed fields explicitly include `app:<app-code>:directory:read`.
|
|
21
21
|
- Derive role grants with `resourceCapabilityCodes(appCode, resourceCode)`. Declare current-user rows only with `currentUserDataPolicy(...)`; do not invent operators, values or alternate current-user spellings.
|
|
22
22
|
- Do not add compatibility aliases, migration branches or silent fallbacks for an earlier 2.0 alpha contract. Replace an incorrect contract and regenerate the application.
|
|
23
|
-
- Standard Workflow and Notification Hub are optional 2.0 modules. Enable them only through the canonical `openxiangda.config.ts` declarations and generated clients; never copy 1.x workflow/message code, tables, APIs, templates or callbacks into this workspace. Keep ordinary CRUD and application-specific state machines independent of them.
|
|
23
|
+
- Standard Workflow and Notification Hub are optional 2.0 modules. Enable them only through the canonical `openxiangda.config.ts` declarations and generated clients; declare each Workflow launch as `standalone`, `custom-page`, `hidden-handoff` or `work-center-only`, put only self-contained standalone launch pages in navigation, and bind durable save handlers with `defineWorkflowLaunchContributions` without repeating generated titles. Desktop and mobile standard launch pages load the same canonical Workflow launch Surface. To replace Workflow detail, declare both desktop and mobile `detailRouteCode` values whose routes contain exactly `:instanceId`; Work Center, the application todo center and notification channels consume the platform-resolved paths, while every Surface and command remains server-authorized. Add the standard current-user todo page only with `adminApplicationTodoCenterPage()`; never query Notification Hub management APIs from a user page. Never depend on temporary router location state or copy 1.x workflow/message code, tables, APIs, templates or callbacks into this workspace. Keep ordinary CRUD and application-specific state machines independent of them.
|
|
24
24
|
- Run `pnpm openxiangda check --json` after contract changes and read `data.sealedArtifact`; check never seals, and an older `.openxiangda/build/app-package.json` is not the current check result. Use `pnpm openxiangda accept --plan <file>` only for optional real preproduction identity acceptance; it never blocks delivery. Deploy with `pnpm openxiangda deploy`, inspect with `pnpm openxiangda status` and `pnpm openxiangda logs`, and use the platform rollback command rather than mutating K3s directly.
|
|
25
|
-
- AI-native clients start the workspace protocol through the same pinned binary: `pnpm exec openxiangda --mcp-stdio --cwd <workspace>`. Read `openxiangda://workspace/contracts` or call `contract_describe`;
|
|
25
|
+
- AI-native clients start the workspace protocol through the same pinned binary: `pnpm exec openxiangda --mcp-stdio --cwd <workspace>`. Read `openxiangda://workspace/contracts` or call `contract_describe`; for first-time menu authoring, copy `data.adminNavigationAuthoring.suggestion.expression` once into `frontend.admin.navigation` with its listed `openxiangda/config` imports, then edit that application-owned declaration. Never treat the proposal as runtime discovery. When AppSpec is enabled, also read `openxiangda://workspace/appspec` or call `appspec_context`. Require `aiCatalog` and `aiCatalogDigest` to match the normal compiler output. This is a stdio transport mode, not another application-owned server. Never write an application MCP server, Catalog file, preview store or second authorization path.
|