openxiangda-cli 2.0.0-alpha.177 → 2.0.0-alpha.179

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/README.md CHANGED
@@ -1,53 +1,9 @@
1
1
  # openxiangda-cli
2
2
 
3
- OpenXiangda 2.0 installs one developer CLI for application creation, connected development, checks, deployment status and logs, explicit retry/cancel, environment start/stop, rollback, login, AppSpec and Skill installation.
3
+ 这是根包 CLI 的内部实现,应用通过 `openxiangda` 安装和运行。命令覆盖创建、上下文、中文资料、开发、统一检查、部署、状态、日志、恢复、环境启停、AppSpec Skill 安装;完整参数运行 `pnpm openxiangda docs cli`。
4
4
 
5
- Deployment recovery is server-authoritative. `status` exposes the root and
6
- latest failures, candidate identity/state, recovery decision and append-only
7
- attempt ledger; `logs` preserves those fields. The CLI follows only the
8
- published recovery command and never advertises cancel after activation.
5
+ 默认开发连接远端测试平台,自定义 Nest 后端按需启用。check 会生成并检查、测试、构建;前置失败时停止。deploy 已包含检查,生产只能晋级成功测试版本。平台 recovery 是恢复操作的权威。
9
6
 
10
- The CLI disables user, development and JIT plugin loading. A clean build removes orphaned command output before TypeScript compilation. `--json` emits one stable result envelope and never mixes progress logs into machine output.
7
+ `--json` 输出一个 `openxiangda.cli-result/v2`。Studio 集成在 create、dev、check、deploy、logs、rollback 使用 `--json-events --run-id <uuid>`,每行一个 `openxiangda.cli-event/v1`;与 --json 互斥。模板引用和摘要成对验证;站点绑定初始化保留 ProjectProvisioningRun Application Git 的权威。
11
8
 
12
- Studio clients use `--json-events` on `create`, `dev`, `check`, `deploy`,
13
- `logs`, and `rollback`. Each stdout line is one
14
- `openxiangda.cli-event/v1` event with a stable AgentRun `--run-id`, ordered
15
- sequence, timestamp and payload; terminal events carry the existing
16
- `openxiangda.cli-result/v2` envelope. `--json` and `--json-events` are mutually
17
- exclusive. `check` remains the only public check entry and reports its internal
18
- test/build stages instead of adding public `test` or `build` commands.
19
-
20
- Studio can create an application with explicit `--app-code` and `--name`.
21
- Custom `--template-ref` and `--template-digest` values must be supplied
22
- together. The reference is either `builtin:application` or a local directory
23
- already materialized by the caller, and the digest is
24
- `sha256:<64 lowercase hex>`. The CLI never fetches a remote template and writes
25
- the verified binding to `.openxiangda/template.json` before installation.
26
-
27
- When the customer site has already created the Application through a Studio
28
- `ProjectProvisioningRun`, use the explicit site-bound mode:
29
-
30
- ```bash
31
- openxiangda create <directory> \
32
- --app-code <platform-app-type> --name <name> \
33
- --template-ref <ref> --template-digest <sha256:digest> \
34
- --studio-project-id <uuid> --provisioning-run-id <uuid> \
35
- --json-events --run-id <execution-uuid>
36
- ```
37
-
38
- This mode never calls application provision and never accepts repository
39
- identity or credentials. It writes a secret-free, fail-closed
40
- `.openxiangda/studio-binding.json` and returns the verified template plus
41
- configuration, contract, AI Catalog and compiler summaries. The site Project
42
- saga remains authoritative for Application and Git readback.
43
-
44
- AI-native development clients use the same pinned executable in pre-command
45
- stdio mode: `pnpm exec openxiangda --mcp-stdio --cwd <workspace>`. They can read
46
- `openxiangda://workspace/contracts` or call `contract_describe` to obtain the
47
- compiler-owned `aiCatalog`, `aiCatalogDigest` and the typed copy-once
48
- `adminNavigationAuthoring.suggestion`. Copy its expression into
49
- `frontend.admin.navigation`; runtime never applies it automatically. This
50
- transport does not add another executable and applications must not implement
51
- a second MCP server.
52
-
53
- `dev` starts local Web/Nest hot reload and a loopback connected proxy. `deploy` defaults to test; production explicitly reuses a successful test AppVersion. Application binding, initialization, generation, tests and builds are internal stages rather than separate commands.
9
+ MCP 复用同一命令的 `--mcp-stdio --cwd <工作区绝对路径>` 模式。插件动态加载已禁用,避免其他命令覆盖当前版本实现。
@@ -1 +1 @@
1
- {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAE7C,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,8BAA8B,EAE/B,MAAM,yBAAyB,CAAC;AAIjC,eAAO,MAAM,cAAc;;CAE1B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;CAmB5B,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;CAGhC,CAAC;AAEF,8BAAsB,kBAAmB,SAAQ,OAAO;IACtD,MAAM,CAAC,cAAc,UAAQ;IAE7B,SAAS,CAAC,QAAQ,CAAC,QAAQ,iCAExB;IACH,OAAO,CAAC,iBAAiB,CAAC,CAAuB;IACjD,OAAO,CAAC,kBAAkB,CAAS;cAEnB,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAiB1D,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;IAuB/C,SAAS,CAAC,oBAAoB;IAI9B,SAAS,CAAC,iBAAiB,CAAC,SAAS,SAAuB;IAa5D,SAAS,CAAC,gBAAgB,CACxB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAWvC,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO;;;;;;;;;;;;;;;;IAqDpC,OAAO,CAAC,QAAQ;IAoChB,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,gBAAgB;CAqCzB"}
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAE7C,OAAO,EAEL,KAAK,YAAY,EAClB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,8BAA8B,EAE/B,MAAM,yBAAyB,CAAC;AAIjC,eAAO,MAAM,cAAc;;CAE1B,CAAC;AAEF,eAAO,MAAM,gBAAgB;;;CAmB5B,CAAC;AAEF,eAAO,MAAM,oBAAoB;;;;CAGhC,CAAC;AAEF,8BAAsB,kBAAmB,SAAQ,OAAO;IACtD,MAAM,CAAC,cAAc,UAAQ;IAE7B,SAAS,CAAC,QAAQ,CAAC,QAAQ,iCAExB;IACH,OAAO,CAAC,iBAAiB,CAAC,CAAuB;IACjD,OAAO,CAAC,kBAAkB,CAAS;cAEnB,KAAK,CAAC,KAAK,EAAE,KAAK,GAAG;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE;IAiB1D,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,OAAO,CAAC;;;;;;;;;;;;;;;;;;;IAuB/C,SAAS,CAAC,oBAAoB;IAI9B,SAAS,CAAC,iBAAiB,CAAC,SAAS,SAAuB;IAa5D,SAAS,CAAC,gBAAgB,CACxB,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAWvC,SAAS,CAAC,WAAW,CAAC,KAAK,EAAE,OAAO;;;;;;;;;;;;;;;;IAmBpC,OAAO,CAAC,QAAQ;IAoChB,OAAO,CAAC,mBAAmB;IAU3B,OAAO,CAAC,WAAW;IAWnB,OAAO,CAAC,gBAAgB;CAqCzB"}
package/dist/base.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { developerError } from 'openxiangda-devkit-core';
1
2
  import { Command, Flags } from "@oclif/core";
2
3
  import { randomUUID } from "node:crypto";
3
4
  import { STUDIO_CLI_RESULT_SCHEMA_VERSION, } from "openxiangda-contracts";
@@ -103,39 +104,13 @@ export class OpenXiangdaCommand extends Command {
103
104
  message.match(/^([A-Z][A-Z0-9_]+)/)?.[1] ||
104
105
  "OPENXIANGDA_COMMAND_FAILED");
105
106
  const nextCommand = this.errorNextCommand(code);
106
- const declaredRemediation = error?.remote?.remediation ||
107
- error?.data?.remediation;
108
- const retryable = Boolean(error?.retryable ||
109
- error?.remote?.retryable ||
110
- (error?.status &&
111
- Number(error.status) >= 500) ||
112
- /NETWORK|TIMEOUT|UNAVAILABLE|RATE_LIMIT/.test(code));
113
- const details = error?.data &&
114
- typeof error.data === "object" &&
115
- !Array.isArray(error.data)
116
- ? (error.data)
117
- : undefined;
118
- const pointer = (details && typeof details.pointer === "string"
119
- ? details.pointer
120
- : undefined) ||
121
- error?.remote?.path;
122
107
  return {
123
108
  schemaVersion: STUDIO_CLI_RESULT_SCHEMA_VERSION,
124
109
  ok: false,
125
110
  operation: this.id || "unknown",
126
111
  workspace: null,
127
112
  data: null,
128
- error: {
129
- code,
130
- message: message.replace(/^([A-Z][A-Z0-9_]+):\s*/, ""),
131
- retryable,
132
- remediation: typeof declaredRemediation === "string"
133
- ? declaredRemediation
134
- : `运行 ${nextCommand}`,
135
- nextCommand,
136
- ...(pointer ? { pointer } : {}),
137
- ...(details ? { details } : {}),
138
- },
113
+ error: developerError(error, nextCommand),
139
114
  };
140
115
  }
141
116
  envelope(result) {
package/dist/base.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"base.js","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../src/base.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAwB,MAAM,YAAY,CAAC;AAEtE,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,SAAqB;IACnC,MAAM,CAAC,KAAK;;;;;MAOV;IAEI,GAAG;;;;;;;;;;;;;;;;;;;CAOV"}
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAwB,MAAM,YAAY,CAAC;AAGtE,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,SAAqB;IACnC,MAAM,CAAC,KAAK;;;;;MAOV;IAEI,GAAG;;;;;;;;;;;;;;;;;;;CAOV"}
@@ -1,11 +1,12 @@
1
1
  import { Flags } from '@oclif/core';
2
2
  import { OpenXiangdaCommand, studioWorkspaceFlags } from '../base.js';
3
+ import { checkApplication, DEVELOPER_ENVIRONMENTS } from 'openxiangda-devkit-core';
3
4
  export default class Check extends OpenXiangdaCommand {
4
5
  static summary = '针对目标平台确定性检查完整应用';
5
6
  static flags = {
6
7
  ...studioWorkspaceFlags,
7
8
  environment: Flags.string({
8
- options: ['test', 'production'],
9
+ options: [...DEVELOPER_ENVIRONMENTS],
9
10
  default: 'test',
10
11
  summary: '兼容性预检目标;默认为 test',
11
12
  }),
@@ -13,8 +14,9 @@ export default class Check extends OpenXiangdaCommand {
13
14
  async run() {
14
15
  const { flags } = await this.parse(Check);
15
16
  this.beginStudioEvents('check');
16
- const environment = flags.environment === 'production' ? 'production' : 'preproduction';
17
- return this.present(await this.services.check(flags.cwd, environment));
17
+ return this.present(await checkApplication(this.services, {
18
+ ...(flags.cwd ? { root: flags.cwd } : {}), environment: flags.environment,
19
+ }));
18
20
  }
19
21
  }
20
22
  //# sourceMappingURL=check.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEtE,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,GAAG,iBAAiB,CAAC;IACnC,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,oBAAoB;QACvB,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;YAC/B,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,kBAAkB;SAC5B,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAChC,MAAM,WAAW,GACf,KAAK,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,eAAe,CAAC;QACtE,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC;IACzE,CAAC"}
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEnF,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,GAAG,iBAAiB,CAAC;IACnC,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,oBAAoB;QACvB,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,CAAC,GAAG,sBAAsB,CAAC;YACpC,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,kBAAkB;SAC5B,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAChC,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE;YACxD,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW;SAC1E,CAAC,CAAC,CAAC;IACN,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { OpenXiangdaCommand } from '../base.js';
2
+ export default class Context extends OpenXiangdaCommand {
3
+ static summary: string;
4
+ static flags: {
5
+ cwd: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
6
+ };
7
+ run(): Promise<import("openxiangda-contracts").DevkitResult<unknown> | {
8
+ schemaVersion: "openxiangda.cli-result/v2";
9
+ ok: boolean;
10
+ operation: string;
11
+ workspace: import("openxiangda-contracts").WorkspaceIdentity | {
12
+ appCode: string;
13
+ name: string | undefined;
14
+ };
15
+ data: {} | null;
16
+ error: {
17
+ details?: Record<string, unknown>;
18
+ pointer?: string;
19
+ code: string;
20
+ message: string;
21
+ retryable: boolean;
22
+ remediation: string;
23
+ nextCommand: string | null;
24
+ } | null;
25
+ } | undefined>;
26
+ }
27
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAkB,MAAM,YAAY,CAAC;AAEhE,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,kBAAkB;IACrD,MAAM,CAAC,OAAO,SAA0B;IACxC,MAAM,CAAC,KAAK;;MAAkB;IACxB,GAAG;;;;;;;;;;;;;;;;;;;CAIV"}
@@ -0,0 +1,10 @@
1
+ import { OpenXiangdaCommand, workspaceFlags } from '../base.js';
2
+ export default class Context extends OpenXiangdaCommand {
3
+ static summary = '只读查看当前工作区、工具链版本与平台绑定';
4
+ static flags = workspaceFlags;
5
+ async run() {
6
+ const { flags } = await this.parse(Context);
7
+ return this.present(await this.services.workspaceContext(flags.cwd));
8
+ }
9
+ }
10
+ //# sourceMappingURL=context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.js","sourceRoot":"","sources":["../../src/commands/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEhE,MAAM,CAAC,OAAO,OAAO,OAAQ,SAAQ,kBAAkB;IACrD,MAAM,CAAC,OAAO,GAAG,sBAAsB,CAAC;IACxC,MAAM,CAAC,KAAK,GAAG,cAAc,CAAC;IAC9B,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC;IACvE,CAAC"}
@@ -6,6 +6,7 @@ export default class Deploy extends OpenXiangdaCommand {
6
6
  from: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
7
7
  "environment-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
8
  "idempotency-key": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ "dry-run": import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
10
  "json-events": import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  "run-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
12
  cwd: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAwB,MAAM,YAAY,CAAC;AACtE,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,kBAAkB;IACpD,MAAM,CAAC,OAAO,SAA2B;IACzC,MAAM,CAAC,KAAK;;;;;;;;MAaV;IACI,GAAG;;;;;;;;;;;;;;;;;;;CA+BV"}
1
+ {"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAwB,MAAM,YAAY,CAAC;AAEtE,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,kBAAkB;IACpD,MAAM,CAAC,OAAO,SAA2B;IACzC,MAAM,CAAC,KAAK;;;;;;;;;MAcV;IACI,GAAG;;;;;;;;;;;;;;;;;;;CAkBV"}
@@ -1,11 +1,12 @@
1
1
  import { Flags } from "@oclif/core";
2
2
  import { OpenXiangdaCommand, studioWorkspaceFlags } from "../base.js";
3
+ import { deployApplication, DEVELOPER_ENVIRONMENTS } from 'openxiangda-devkit-core';
3
4
  export default class Deploy extends OpenXiangdaCommand {
4
5
  static summary = "部署到测试环境,或显式复用测试版本部署生产";
5
6
  static flags = {
6
7
  ...studioWorkspaceFlags,
7
8
  environment: Flags.string({
8
- options: ["test", "production"],
9
+ options: [...DEVELOPER_ENVIRONMENTS],
9
10
  default: "test",
10
11
  summary: "目标环境;默认为 test",
11
12
  }),
@@ -13,24 +14,18 @@ export default class Deploy extends OpenXiangdaCommand {
13
14
  summary: "生产部署复用的成功测试 DeploymentRun ID",
14
15
  dependsOn: ["environment"],
15
16
  }),
16
- "environment-id": Flags.string(),
17
- "idempotency-key": Flags.string(),
17
+ "environment-id": Flags.string({ summary: '测试环境 ID;通常由绑定自动确定' }),
18
+ "idempotency-key": Flags.string({ summary: '测试部署幂等键;省略时从不可变包摘要派生' }),
19
+ "dry-run": Flags.boolean({ summary: '只读预览部署或生产晋级,不构建、不上传、不提交' }),
18
20
  };
19
21
  async run() {
20
22
  const { flags } = await this.parse(Deploy);
21
23
  this.beginStudioEvents("deploy");
22
- if (flags.environment === "production") {
23
- if (!flags.from) {
24
- throw new Error("PRODUCTION_TEST_DEPLOYMENT_REQUIRED: 使用 --from <test-deployment-id> 复用已验证版本");
25
- }
26
- return this.present(await this.services.deployProduction(flags.cwd, flags.from));
27
- }
28
- if (flags.from) {
29
- throw new Error("DEPLOY_TEST_FROM_INVALID: --from 只允许与 --environment production 一起使用");
30
- }
31
- return this.present(await this.services.deploy({
24
+ return this.present(await deployApplication(this.services, {
32
25
  ...(flags.cwd ? { root: flags.cwd } : {}),
33
- environment: "preproduction",
26
+ environment: flags.environment,
27
+ ...(flags.from ? { from: flags.from } : {}),
28
+ dryRun: flags['dry-run'],
34
29
  ...(flags["environment-id"]
35
30
  ? { environmentId: flags["environment-id"] }
36
31
  : {}),
@@ -1 +1 @@
1
- {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACtE,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,kBAAkB;IACpD,MAAM,CAAC,OAAO,GAAG,uBAAuB,CAAC;IACzC,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,oBAAoB;QACvB,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,CAAC,MAAM,EAAE,YAAY,CAAC;YAC/B,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,eAAe;SACzB,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,OAAO,EAAE,8BAA8B;YACvC,SAAS,EAAE,CAAC,aAAa,CAAC;SAC3B,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,MAAM,EAAE;QAChC,iBAAiB,EAAE,KAAK,CAAC,MAAM,EAAE;KAClC,CAAC;IACF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,WAAW,KAAK,YAAY,EAAE,CAAC;YACvC,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CACb,6EAA6E,CAC9E,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,CAAC,OAAO,CACjB,MAAM,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAC5D,CAAC;QACJ,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;QACJ,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CACjB,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;YACzB,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,WAAW,EAAE,eAAe;YAC5B,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC;gBACzB,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE;gBAC5C,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC;gBAC1B,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,iBAAiB,CAAC,EAAE;gBAC9C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CACH,CAAC;IACJ,CAAC"}
1
+ {"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../src/commands/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACpF,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,kBAAkB;IACpD,MAAM,CAAC,OAAO,GAAG,uBAAuB,CAAC;IACzC,MAAM,CAAC,KAAK,GAAG;QACb,GAAG,oBAAoB;QACvB,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,CAAC,GAAG,sBAAsB,CAAC;YACpC,OAAO,EAAE,MAAM;YACf,OAAO,EAAE,eAAe;SACzB,CAAC;QACF,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC;YACjB,OAAO,EAAE,8BAA8B;YACvC,SAAS,EAAE,CAAC,aAAa,CAAC;SAC3B,CAAC;QACF,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,mBAAmB,EAAE,CAAC;QAChE,iBAAiB,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC;QACpE,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC;KACjE,CAAC;IACF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAC3C,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QACjC,OAAO,IAAI,CAAC,OAAO,CACjB,MAAM,iBAAiB,CAAC,IAAI,CAAC,QAAQ,EAAE;YACrC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACzC,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3C,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC;YACxB,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC;gBACzB,CAAC,CAAC,EAAE,aAAa,EAAE,KAAK,CAAC,gBAAgB,CAAC,EAAE;gBAC5C,CAAC,CAAC,EAAE,CAAC;YACP,GAAG,CAAC,KAAK,CAAC,iBAAiB,CAAC;gBAC1B,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,iBAAiB,CAAC,EAAE;gBAC9C,CAAC,CAAC,EAAE,CAAC;SACR,CAAC,CACH,CAAC;IACJ,CAAC"}
@@ -0,0 +1,30 @@
1
+ import { OpenXiangdaCommand } from '../base.js';
2
+ export default class Docs extends OpenXiangdaCommand {
3
+ static summary: string;
4
+ static args: {
5
+ topic: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
6
+ };
7
+ static flags: {
8
+ section: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
+ };
10
+ run(): Promise<import("openxiangda-contracts").DevkitResult<unknown> | {
11
+ schemaVersion: "openxiangda.cli-result/v2";
12
+ ok: boolean;
13
+ operation: string;
14
+ workspace: import("openxiangda-contracts").WorkspaceIdentity | {
15
+ appCode: string;
16
+ name: string | undefined;
17
+ };
18
+ data: {} | null;
19
+ error: {
20
+ details?: Record<string, unknown>;
21
+ pointer?: string;
22
+ code: string;
23
+ message: string;
24
+ retryable: boolean;
25
+ remediation: string;
26
+ nextCommand: string | null;
27
+ } | null;
28
+ } | undefined>;
29
+ }
30
+ //# sourceMappingURL=docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.d.ts","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,kBAAkB;IAClD,MAAM,CAAC,OAAO,SAA6B;IAC3C,MAAM,CAAC,IAAI;;MAAwD;IACnE,MAAM,CAAC,KAAK;;MAAiE;IACvE,GAAG;;;;;;;;;;;;;;;;;;;CAUV"}
@@ -0,0 +1,20 @@
1
+ import { Args, Flags } from '@oclif/core';
2
+ import { documentationIndex, readDocumentation } from 'openxiangda-devkit-core';
3
+ import { OpenXiangdaCommand } from '../base.js';
4
+ export default class Docs extends OpenXiangdaCommand {
5
+ static summary = '读取当前版本的中文使用资料;不传主题时显示目录';
6
+ static args = { topic: Args.string({ summary: '文档目录中的稳定主题 ID' }) };
7
+ static flags = { section: Flags.string({ summary: '主题目录中的章节 ID;按需读取长文档' }) };
8
+ async run() {
9
+ const { args, flags } = await this.parse(Docs);
10
+ if (flags.section && !args.topic)
11
+ throw new Error('DOCUMENTATION_TOPIC_REQUIRED: 读取章节时必须指定主题');
12
+ const data = args.topic ? readDocumentation(args.topic, flags.section) : documentationIndex();
13
+ if (!this.jsonEnabled()) {
14
+ this.log('content' in data ? data.content : data.topics.map(topic => `${topic.id} ${topic.title}`).join('\n'));
15
+ return;
16
+ }
17
+ return this.present({ ok: true, operation: 'docs', workspace: { appCode: 'global', root: process.cwd() }, data, diagnostics: [], nextActions: [] });
18
+ }
19
+ }
20
+ //# sourceMappingURL=docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs.js","sourceRoot":"","sources":["../../src/commands/docs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,IAAK,SAAQ,kBAAkB;IAClD,MAAM,CAAC,OAAO,GAAG,yBAAyB,CAAC;IAC3C,MAAM,CAAC,IAAI,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;IACnE,MAAM,CAAC,KAAK,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,EAAE,CAAC;IAC7E,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC/C,IAAI,KAAK,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;QAC/F,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC;QAC9F,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,IAAI,CAAC,GAAG,CAAC,SAAS,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,EAAE,KAAK,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YAChH,OAAO;QACT,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,CAAC,CAAC;IACtJ,CAAC"}
@@ -5,6 +5,7 @@ export default class Skill extends OpenXiangdaCommand {
5
5
  action: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
6
6
  };
7
7
  static flags: {
8
+ workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
8
9
  destination: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
9
10
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
10
11
  };
@@ -1 +1 @@
1
- {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,SAA2C;IACzD,MAAM,CAAC,IAAI;;MAET;IACF,MAAM,CAAC,KAAK;;;MASV;IAEI,GAAG;;;;;;;;;;;;;;;;;;;CAuBV"}
1
+ {"version":3,"file":"skill.d.ts","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,SAA2C;IACzD,MAAM,CAAC,IAAI;;MAET;IACF,MAAM,CAAC,KAAK;;;;MAUV;IAEI,GAAG;;;;;;;;;;;;;;;;;;;CA2BV"}
@@ -1,7 +1,9 @@
1
1
  import { Args, Flags } from '@oclif/core';
2
+ import { readFileSync } from 'node:fs';
3
+ import { workspaceGuidanceTemplatePath } from 'openxiangda-devkit-core';
2
4
  import { homedir } from 'node:os';
3
5
  import { join, resolve } from 'node:path';
4
- import { installSkills, resolveDefaultSkillsRoot, } from 'openxiangda-skill-kit';
6
+ import { installSkills, refreshWorkspaceGuidance, resolveDefaultSkillsRoot, } from 'openxiangda-skill-kit';
5
7
  import { OpenXiangdaCommand } from '../base.js';
6
8
  export default class Skill extends OpenXiangdaCommand {
7
9
  static summary = '安装或更新与当前 openxiangda 版本完全一致的 AI Skill';
@@ -9,6 +11,7 @@ export default class Skill extends OpenXiangdaCommand {
9
11
  action: Args.string({ required: true, options: ['install'] }),
10
12
  };
11
13
  static flags = {
14
+ workspace: Flags.string({ summary: '安装到指定项目的 .agents/skills,并刷新 AGENTS.md 平台区块', helpValue: '<directory>' }),
12
15
  destination: Flags.string({
13
16
  summary: 'AI Skill 根目录;默认使用 Codex Skill 目录',
14
17
  helpValue: '<directory>',
@@ -24,17 +27,21 @@ export default class Skill extends OpenXiangdaCommand {
24
27
  throw new Error(`OPENXIANGDA_SKILL_ACTION_UNSUPPORTED:${args.action}`);
25
28
  }
26
29
  const destination = resolve(flags.destination ||
30
+ (flags.workspace ? join(resolve(flags.workspace), '.agents/skills') : undefined) ||
27
31
  join(process.env.CODEX_HOME || join(homedir(), '.codex'), 'skills'));
28
32
  const result = await installSkills({
29
33
  skillsRoot: resolveDefaultSkillsRoot(),
30
34
  destination,
31
35
  force: flags.force,
32
36
  });
37
+ const guidance = flags.workspace
38
+ ? refreshWorkspaceGuidance(resolve(flags.workspace), readFileSync(workspaceGuidanceTemplatePath(), 'utf8'))
39
+ : undefined;
33
40
  return this.present({
34
41
  ok: true,
35
42
  operation: 'skill install',
36
43
  workspace: { appCode: 'global', root: process.cwd() },
37
- data: result,
44
+ data: { ...result, ...(guidance ? { guidance } : {}) },
38
45
  diagnostics: [],
39
46
  nextActions: [],
40
47
  });
@@ -1 +1 @@
1
- {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,aAAa,EACb,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,GAAG,uCAAuC,CAAC;IACzD,MAAM,CAAC,IAAI,GAAG;QACZ,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;KAC9D,CAAC;IACF,MAAM,CAAC,KAAK,GAAG;QACb,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,kCAAkC;YAC3C,SAAS,EAAE,aAAa;SACzB,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,kBAAkB;SAC5B,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,WAAW,GAAG,OAAO,CACzB,KAAK,CAAC,WAAW;YACf,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CACtE,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,UAAU,EAAE,wBAAwB,EAAE;YACtC,WAAW;YACX,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC,CAAC;QACH,OAAO,IAAI,CAAC,OAAO,CAAC;YAClB,EAAE,EAAE,IAAI;YACR,SAAS,EAAE,eAAe;YAC1B,SAAS,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;YACrD,IAAI,EAAE,MAAM;YACZ,WAAW,EAAE,EAAE;YACf,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;IACL,CAAC"}
1
+ {"version":3,"file":"skill.js","sourceRoot":"","sources":["../../src/commands/skill.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,6BAA6B,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,aAAa,EACb,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,kBAAkB;IACnD,MAAM,CAAC,OAAO,GAAG,uCAAuC,CAAC;IACzD,MAAM,CAAC,IAAI,GAAG;QACZ,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC;KAC9D,CAAC;IACF,MAAM,CAAC,KAAK,GAAG;QACb,SAAS,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,4CAA4C,EAAE,SAAS,EAAE,aAAa,EAAE,CAAC;QAC5G,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC;YACxB,OAAO,EAAE,kCAAkC;YAC3C,SAAS,EAAE,aAAa;SACzB,CAAC;QACF,KAAK,EAAE,KAAK,CAAC,OAAO,CAAC;YACnB,OAAO,EAAE,KAAK;YACd,OAAO,EAAE,kBAAkB;SAC5B,CAAC;KACH,CAAC;IAEF,KAAK,CAAC,GAAG;QACP,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,MAAM,WAAW,GAAG,OAAO,CACzB,KAAK,CAAC,WAAW;YACf,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YAChF,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC,CACtE,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,UAAU,EAAE,wBAAwB,EAAE;YACtC,WAAW;YACX,KAAK,EAAE,KAAK,CAAC,KAAK;SACnB,CAAC,CAAC;QACH,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS;YAC9B,CAAC,CAAC,wBAAwB,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,YAAY,CAAC,6BAA6B,EAAE,EAAE,MAAM,CAAC,CAAC;YAC3G,CAAC,CAAC,SAAS,CAAC;QACd,OAAO,IAAI,CAAC,OAAO,CAAC;YAClB,EAAE,EAAE,IAAI;YACR,SAAS,EAAE,eAAe;YAC1B,SAAS,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,EAAE;YACrD,IAAI,EAAE,EAAE,GAAG,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;YACtD,WAAW,EAAE,EAAE;YACf,WAAW,EAAE,EAAE;SAChB,CAAC,CAAC;IACL,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "openxiangda-cli",
3
- "version": "2.0.0-alpha.177",
4
- "description": "Thin application-level CLI for OpenXiangda 2.0.",
3
+ "version": "2.0.0-alpha.179",
4
+ "description": "OpenXiangda 2.0 应用生命周期命令、创建器与模板。",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -21,10 +21,10 @@
21
21
  ],
22
22
  "dependencies": {
23
23
  "@oclif/core": "4.13.3",
24
- "openxiangda-contracts": "2.0.0-alpha.89",
25
- "openxiangda-devkit-core": "2.0.0-alpha.114",
26
- "openxiangda-mcp": "2.0.0-alpha.114",
27
- "openxiangda-skill-kit": "2.0.0-alpha.139"
24
+ "openxiangda-contracts": "2.0.0-alpha.90",
25
+ "openxiangda-devkit-core": "2.0.0-alpha.115",
26
+ "openxiangda-mcp": "2.0.0-alpha.115",
27
+ "openxiangda-skill-kit": "2.0.0-alpha.140"
28
28
  },
29
29
  "devDependencies": {
30
30
  "tsx": "4.23.12",
@@ -1,64 +1,23 @@
1
- # OpenXiangda 2.0 Application Agent Contract
1
+ # 应用开发约定
2
2
 
3
- - Use only the workspace-pinned CLI: `pnpm openxiangda <command>`. Never invoke a bare global `openxiangda` inside a 2.0 task.
4
- - Maintain business goals, task pages, permission decisions and acceptance examples in the existing `appspec/app.md`; complex modules may have focused capability records. `appspec/` is the 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
- - Use Vite, React Router, Refine Core and platform Field Kit. Use Ant Design for PC and the scoped openxiangda/mobile adapter for touch controls; wrap custom mobile pages in MobileSurface and import openxiangda/mobile/styles.css. Do not import the antd-mobile root with its global reset. Do not author raw business input/select/textarea/contentEditable elements. Keep mobile entrypoints under src/mobile/ or name them Mobile*.tsx / *.mobile.tsx so openxiangda check can inspect their local dependency graph. Do not add Umi, ProComponents or another admin shell.
6
- - Use Ant Design's default component appearance on PC and the platform's scoped mobile adapter for touch controls. The UI provider supplies Chinese locale and contextual feedback only. Do not generate appearance preferences, color configuration, palette registries, visual state stores or document-wide color effects. Prefer platform components and keep CSS scoped to the component.
7
- - The template includes Tailwind CSS v4 utilities for user pages. The application owns its minimal document reset; omit preflight from the shared runtime and do not scaffold custom palettes.
8
- - 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. Generated resource CRUD routes are compiler-owned under `/admin/resources/<resourceCode>...` and `/m/admin/resources/<resourceCode>...`; never recreate root resource paths, aliases or redirects. Explicit routes that have the same canonical shape as another explicit or generated route fail compilation, even when dynamic parameter names differ. Use only the 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.
9
- - Application login is optional `frontend.authentication`: existing platform users only, registration rejected, exact desktop `/login` and mobile `/m/login`. Bind generated `authenticationSurfaces` to separate PC/mobile renderers through `defineApplicationContributions`; renderers own only brand visuals and call `ApplicationLoginSurfaceProps`. The platform alone owns passwords, providers, OAuth state/callbacks, secure cookies, current identity and authorization. Never put login in protected `appRoutes`, call a v1 auth route, store tokens, create users/roles, or add another Router/identity provider. Keep QA in generated `platformAuthManifest`, outside the protected route denominator.
10
- - Branded standard user pages use the optional exact `standardUserSurfaces` contribution from `openxiangda/react`: provide separate desktop/mobile `frame` and `applicationTodoCenter` renderers or omit the property entirely. The platform still owns `/todos`, `/m/todos`, Workflow routes, `RuntimeBoundary`, current-user Notification Hub data, query/load/interaction callbacks and navigation. Never add a second Router, Todo API client, identity store or token prop.
11
- - External users without platform accounts use only an exact static `surface: 'user'` route declared through `frontend.publicAccess`. Declare the one resource, bounded field sets, required operations, draft limits and named duplicate validations; consume only generated `anonymousPublicAccess` and `createAnonymousPublicClient`. `own.list`/`own.read` mean records submitted by the same platform-issued HttpOnly browser credential, not a verified natural person, and another browser or cleared cookie intentionally loses access. Never create a guest role/user, call the general Native Data API, expose an anonymous upload path, store identity locally or derive ownership from IP, user-agent or fingerprint.
12
- - Define storage with `defineDataModel` in `modules/<business>/models.ts`; compose modules with `defineApplicationModule`. Select standard pages explicitly through `crud`, `defineResourceList` and `defineResourceForm`. Models without `crud` receive no pages or navigation. A business task page may consume several models. The root `openxiangda.config.ts` composes modules, routes and roles; it must not grow into one giant business definition. Existing `data.resources` remains a lower-level input to the same compiler. Keep internal fields `hidden: true`; this is presentation, never authorization. `system: true` marks server-owned values and hides them by default; `hidden: false` may show a business status or serial number. Form/detail/list field selections are exhaustive and ordered. A Workflow subject resource may declare explicit desktop/mobile `detailRouteCode` as documented in the workflow contract.
13
- - 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`.
14
- - 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.
15
- - Standard PC lists use one toolbar, on-demand filters/column settings and drawer create/edit over the retained list. Full-page entry uses the same platform form. Declare shared form/detail groups with `crud[].sections: [{ title, fields }]`; each view's field selection remains exhaustive and ordered. Small forms may omit groups. Keep only business columns by default, use lightweight sections and let platform components handle pending, errors and dirty cancellation. Do not recreate list/form layouts in application code.
16
- - Add NestJS only for a named business action that needs a cross-resource transaction, an invariant or an external side effect. The blank app contains no apps/server source or Nest dependency importer. Declare backend.enabled or a server operation, then run pnpm openxiangda check or pnpm dev to initialize and install the optional backend once; existing source is never regenerated. Standard platform workflow definitions and activations do not require Nest.
17
- - One model can declare up to 20 named standard views with `crud[].code` and `name`. Each selects its own list/form/detail fields, sections, generated operations and mobile availability. Bind navigation with `adminResourcePage(modelCode, { viewCode })`; only an unnamed CRUD declaration generates the original default routes. Views share model values, access and Data API ownership. Include writable required fields in create forms or set `generated.create: false`. Keep platform display preferences and authenticated drafts scoped to the selected view; do not copy models or invent a second draft store.
18
- - Every interactive business action binds `@OpenXiangdaOperation(operation)` and injects `OpenXiangdaBusinessDataApiService`, `OpenXiangdaBusinessNotificationService`, or `OpenXiangdaStandardOperations`. The platform checks the action capability once at App API ingress; the trusted backend then has full Data/managed business-notification access only to its exact application/environment while audit retains the initiating user and action. Do not author `authorizationJSON`, forward user tokens, grant ordinary users `app:notification2:send`, or reapply the user's resource, row and field permissions inside the action.
19
- - A NestJS backend declares only `enabled`, `isolation: 'shared' | 'dedicated'` and `resourceProfile: 'light' | 'standard'`. Never put raw Kubernetes resources, replicas, ports or environment maps in application metadata; the platform owns capacity and scaling.
20
- - Use the current logged-in user and the union of that user's application roles. An app for every logged-in platform user may declare one existing package role through `authz.authenticatedUserRoleCode`; the platform materializes it on first access and unions it with manual and business-projected roles. Do not fabricate a browser fallback role or use a business membership resource for this universal audience. An optional declared Perspective projects only read visibility (pages, rows and fields); create/update/delete, workflows and custom actions continue to authorize against the complete union. Standard Data API calls inherit `X-OpenXiangda-Perspective` automatically. Use `@CurrentPerspective()` only when custom Nest code reads outside the standard Data API, and apply an equivalent read projection explicitly. Business code must not persist a platform Token or authorization result and must not implement a second identity path.
21
- - Fields inherit the resource read/create/update capabilities. Use field `access` only to tighten them; arrays are all-of and `false` is explicit deny. There is no `write` fallback.
22
- - Field `type` is semantic, never a hand-authored database type. The supported catalog is exactly `text.short`, `text.long`, `text.rich`, `number.integer`, `number.decimal`, `boolean`, `date`, `time`, `datetime`, `date-range`, `datetime-range`, `option.single`, `option.multiple`, `cascade.single`, `cascade.multiple`, `user.single`, `user.multiple`, `department.single`, `department.multiple`, `resource-ref.single`, `resource-ref.multiple`, `file`, `image`, `signature`, `address`, `location`, `json`, `serial-number`, `uuid` and `subtable`. The compiler alone derives PostgreSQL columns, constraints and indexes.
23
- - Every `date-range` and `datetime-range` field explicitly declares `rangeBoundary: 'closed' | 'half-open'`. Values remain `{ start, end }`; callers never send or override the boundary. Closed ranges allow `start <= end` and use PostgreSQL `[]`; half-open ranges require `start < end` and use `[)`.
24
- - Declare every custom operation capability in `authz.capabilities` with `kind: 'backend'`, then reference that same code from the operation and its allowed roles. Generated resource CRUD capabilities do not go in this catalog.
25
- - Build App Operation request/response schemas with `resourceRecordSchema`, `schemaRef`, `composeJsonSchema` and `composeAppOperationSchemas` from `openxiangda/config`. They project the same Resource declaration and canonical field value protocols; never import a physical toolchain package or repeat user, department, resource-reference or managed-file schemas by hand.
26
- - Visitor duplicate protection uses `createVisitorReservation({ duplicateMatch: { fieldCode: submittedValue }, ... })`. `duplicateMatch` is a non-empty value map, never a field-name array, and no mutable pre-read is allowed.
27
- - Desktop and mobile pages share values, validation and authorization, but use separate renderers. Options, members and departments store display snapshots; resource references store direct JSON display values; attachments, images and signatures use platform-managed file references.
28
- - `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`.
29
- - Use `resourceRoleCapabilities(appCode, resourceCode, "read" | "manage" | [operations])` for explicit role grants. A read grant never expands into create/update/delete when a page is added. Confirm the business permission matrix before implementing multi-role behavior; `manage` is only for roles explicitly allowed all CRUD operations. Use `currentUserDataPolicy(...)` for current-user row scope.
30
- - 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.
31
- - Standard Workflow and Notification Hub are optional 2.0 modules. Enable them only through canonical `openxiangda.config.ts` declarations and generated clients. `standalone`/`hidden-handoff` default to the compiler-owned process operation; action-owned submission must instead declare `launch.submission.kind: 'named-operation'` with sealed create/existing input and output bindings so the standard PC/mobile page calls the original Named Action and accepts an explicit no-Workflow result. Never add a browser save callback or call Workflow prepare/start directly. Custom pages launch only through a verified Named Action using `OpenXiangdaBusinessProcessService`. PC and mobile render the same `ProcessCommandSurface` independently and recover only by `commandId`. To replace Workflow detail, declare both desktop and mobile `detailRouteCode` values whose routes contain exactly `:instanceId`. Add the current-user todo page only with `frontend.user.applicationTodoCenter: true`; never query Notification Hub management APIs from a user page.
32
- - 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.
33
- - 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.
3
+ <!-- OPENXIANGDA:BEGIN -->
4
+ ## 平台约定
34
5
 
35
- - For an ordinary CRUD module, omit unused backend/platform blocks; the platform owns CRUD. `pnpm dev` uses connected development and starts Nest only when enabled or required by declared server capabilities. Run interface tests for changed business rules and browser tests for the actual PC/mobile create/edit/save/read journeys; passing HTTP tests alone is not acceptance.
6
+ 本项目使用 OpenXiangda 2.0。进入项目后以本地精确依赖和锁文件为准,使用 `pnpm openxiangda`;先运行 `context --json` 确认版本和绑定,使用 `docs` 按任务读取当前中文资料。
36
7
 
8
+ - 模型、页面、导航和权限由应用声明一次;编译器生成契约。业务代码不改生成结果、不创建 platform/data、不复制平台 Router、字段组件、客户端或权限状态。
9
+ - 当前用户、角色并集、数据授权和部署状态归平台;应用不保存凭据或授权快照。普通 CRUD 走 Data API,真实业务动作才按需启用 Nest。
10
+ - 标准业务字段使用 `openxiangda/field-kit`;PC 补充控件使用 antd,移动使用有作用域的 `openxiangda/mobile` 和 MobileSurface,不引入上游全局重置。
11
+ - 无账号表单读取 `docs public-access`,使用 frontend.publicAccess 和专用客户端;标准审批、通知和后端均按需启用。
12
+ - 日常使用 dev 和聚焦测试。只验证时使用 check;授权部署时直接 deploy,它已包含检查、测试和构建。生产必须指定成功测试运行并复用同一版本。
13
+ - 根据变化风险记录业务意图。无行为变化不新建 AppSpec;已有授权和已确认意图不重复向用户请求机械确认。真实角色和浏览器验收与本地测试分别记录。
14
+ - 失败保留错误码、指针和原候选;查询平台状态后使用允许的恢复操作,不自动重放未知结果。
37
15
 
38
- ## Standard data entry and list controls
16
+ MCP 使用同一项目 CLI:`pnpm exec openxiangda --mcp-stdio --cwd <workspace>`。先读取 workspace_context,再按任务读取 docs_read 和当前契约。登录、创建及长期 dev 使用 CLI/终端。
39
17
 
40
- Use the platform standard list for nested AND/OR conditions, display-column
41
- selection/order/freezing and multiple sorting. Set `requiresSelection: true` on
42
- selection-dependent toolbar contributions. Preserve hidden fields and query /
43
- export parity. Column changes preview immediately and save to current-user
44
- platform preferences explicitly.
18
+ 详细用法:`pnpm openxiangda docs development`、`docs frontend`、`docs data-authz`、`docs administration`、`docs testing`、`docs delivery`。按需加载,无需每次通读全部资料。
19
+ <!-- OPENXIANGDA:END -->
45
20
 
46
- Standard forms use Save draft / Submit. Consume platform authenticated drafts;
47
- do not create application draft tables, localStorage or Nest draft endpoints.
48
- PC drawer controls are Full screen / New page / Close, with a platform draft
49
- handoff to the new page. Mobile entry uses grouped touch-field rows, a simple
50
- title and a fixed action footer, with bottom sheets for drafts and recovery.
51
- Do not add a mobile Back to list action or desktop form controls. Preserve edit
52
- revisions and draft CAS; successful submission consumes the draft atomically.
21
+ ## 项目自有约定
53
22
 
54
- ## Optional application backend
55
-
56
- For an already deployed standard workflow, first inspect `pnpm openxiangda admin workflow <workflowCode> --json` (add `--environment production` only for production inspection). The platform owns administrator node parameters; local definitions own topology. Do not overwrite runtime overrides during code authoring. Existing tasks retain their frozen parameters and future node entries use the latest configuration.
57
-
58
- The default scaffold contains Web and shared contracts only. Declare
59
- `backend: { enabled: true }` or application server capabilities, then use the
60
- existing `pnpm openxiangda check` / `pnpm dev` loop. The tool initializes Nest
61
- source and its exact dependencies once, preserves authored source, and retries
62
- an interrupted dependency install. Standard platform workflow activation does
63
- not imply application Nest. See `docs/backend.md` and the runnable
64
- `examples/business-action-extension` for SDK ownership and transaction retries.
23
+ 在此补充本项目的业务范围和团队要求;平台资料刷新保留本节内容。
@@ -1,70 +1,45 @@
1
- # OpenXiangda 2.0 应用模板
1
+ # OpenXiangda 2.0 应用
2
2
 
3
- 这是从业务任务开始的应用模板:Vite + React Router + Refine Core,优先消费平台 Field Kit。PC 使用 Ant Design,移动录入使用 Ant Design Mobile。标准 CRUD 直接调用平台 Data API,默认没有 Nest 后端源码和依赖。声明服务端执行能力后,`pnpm openxiangda check` 或 `pnpm dev` 才会初始化 `apps/server` 并安装依赖。
3
+ 本项目使用精确版本的 openxiangda 根包。默认包含 Web 和共享契约,普通 CRUD、标准审批与通知由平台执行;真实业务动作才按需启用 Nest
4
+
5
+ ## 开始
4
6
 
5
7
  ```bash
8
+ pnpm install --frozen-lockfile
9
+ pnpm openxiangda context --json
6
10
  pnpm openxiangda dev
7
11
  ```
8
12
 
9
- 当前应用只直接依赖一个精确版本的 `openxiangda` 根包,并在 lockfile 中锁定其内部实现包。创建另一个应用时使用当前安装的 OpenXiangda 2.0 Skill 给出的精确根包版本,不使用 `latest`、`alpha` 或全局命令。
10
-
11
- `appspec/app.md` 是默认保留的业务意图总纲,帮助人和 AI 理解当前需求,但不是发布门禁。没有行为变化
12
- 时不写变更;小改动最多维护一份短 ChangeSpec。按需使用
13
- `pnpm openxiangda spec context --json`、`spec new` 和 `spec close`,不要引入 1.x `openspec/SDD`。
13
+ 依赖已安装时无需重复安装。开发连接已绑定的远端测试数据,终端和页面显示实际环境。缺少账号或绑定时按命令错误提示处理;不要调用旧版全局 CLI。
14
14
 
15
- 按业务模块拆分文件:`modules/<业务>/models.ts` 定义 `defineDataModel`,`views.ts` 定义 `defineResourceList` / `defineResourceForm`,模块入口用 `defineApplicationModule` 组合。只有显式放入模块 `crud` 的模型才生成标准页;辅助模型可以完全没有页面,业务任务页也可以消费多个模型。根 `openxiangda.config.ts` 只组合模块、页面和权限。列表、表单、详情可分别选择字段,未选择字段不会自动补回。`hidden: true` 隐藏内部字段,但不改变其服务端权限。
15
+ ## 阅读资料
16
16
 
17
- 成员、部门分别声明 `user.single`/`user.multiple` 和 `department.single`/`department.multiple`;同应用动态资源声明 `resource-ref.single`/`resource-ref.multiple` 及编译期固定的 `source`。这些字段都保存完整 `{label,value,...}` 显示快照,资源引用还保存 `resourceCode` 和声明的 `snapshot` 字段;查询和权限以稳定 `value` 为比较键。资源来源的 `labelField` 只能引用 `text.short` 或 `text.long`;流水号可用于搜索、描述和快照,不能作为显示标签。需要目录选择器的业务角色必须显式拥有 `app:<app-code>:directory:read` 能力。用 `resourceRoleCapabilities(appCode, resourceCode, "read" | "manage" | [operations])` 显式选择角色权限;只读角色不会因生成页面而自动获得写权限,用 `currentUserDataPolicy` 声明唯一的当前用户行规则。
17
+ ```bash
18
+ pnpm openxiangda docs
19
+ pnpm openxiangda docs development
20
+ pnpm openxiangda docs application-foundation
21
+ pnpm openxiangda docs frontend
22
+ pnpm openxiangda docs data-authz
23
+ ```
18
24
 
19
- 字段组件、CRUD Renderer、Shell、Runtime Data/Directory/File/App Client 都由 `openxiangda/react`、`openxiangda/field-kit` 和 `openxiangda/core` 统一提供,应用模板不复制这些实现。Nest 只在需要复杂事务或外部集成时增加 App API。标准客户端显式携带当前环境、使用同源 Cookie;业务代码不读取或持久化 Token、平台内部身份标识与授权结果。
25
+ 资料来自当前根包;长主题支持 --section <章节ID>。AGENTS.md 的平台段说明基本约定,项目自有内容保留在该段之外。AI Skill 按任务读取同源资料。
20
26
 
21
- 同一应用的自定义后台页、PC 用户页和移动用户页统一声明在
22
- `frontend.routes`,再用 `defineApplicationContributions(appRoutes, { pages })`
23
- 逐项绑定本地组件并传给 `OpenXiangdaApplication`。后者是唯一的
24
- BrowserRouter、RuntimeBoundary、Refine、generated routes 和后台 Shell
25
- 所有者;用户页可以拥有独立布局,但不要再建 router/Shell。要使用通用应用待办中心,
26
- 声明 `frontend.user.applicationTodoCenter: true`;平台生成 `/todos` 与 `/m/todos`,
27
- 只读取当前用户的消息/待办投影并统一解析目标页面。
27
+ ## 声明与页面
28
28
 
29
- 自定义后台页使用 `OpenXiangdaAdminPage` 作为页面根,优先使用平台组件与 Ant Design
30
- 默认组件。平台只统一中文语言和消息上下文,不提供外观偏好或配色配置。组件样式应限定
31
- 在自身范围,文档级 margin/height 重置由 `apps/web/src/document.css` 负责。
29
+ 业务模型和页面选择保存在 modules,应用根配置负责装配。模型不隐含导航或写授权。字段与标准 CRUD 使用平台组件;PC 控件使用 antd,移动使用 openxiangda/mobile。应用负责最小文档重置和局部样式,不直接导入 antd-mobile 全局重置。
32
30
 
33
- 模板提供 Tailwind CSS v4 默认工具类,供用户端业务页面编排布局;不引入全局 preflight,
34
- 不生成额外色板。移动业务输入使用 `openxiangda/mobile` 和平台 Field Kit。
31
+ apps/server 仅在启用后端时初始化。后续 check/dev 保留业务源码,普通 CRUD 不增加 controller。
35
32
 
36
- 登录声明位于 `frontend.authentication`,只允许现有平台用户并拒绝注册。桌面 `/login`
37
- 与移动 `/m/login` 是独立生成的 `authenticationSurfaces`,不计入受保护的
38
- `appRoutes`。用 `defineApplicationContributions({ routes: appRoutes,
39
- authenticationSurfaces }, { pages, authentication })` 分别绑定 PC/移动品牌 renderer;
40
- renderer 只使用 `ApplicationLoginSurfaceProps` 回调,不能验证密码、读取 Token、处理
41
- OAuth callback 或创建第二个 Router/身份状态。`platformAuthManifest` 单独记录登录面 QA,
42
- 不会改变用户路由覆盖数。
33
+ ## 检查与发布
43
34
 
44
- 如需统一品牌化普通用户页面,在应用入口给
45
- `defineApplicationContributions` 增加完整的 `standardUserSurfaces`:必须同时提供
46
- `frame.desktop/mobile` 与 `applicationTodoCenter.desktop/mobile`。外框只使用
47
- `StandardUserPageFrameProps` 的页面类型、安全路由元数据、`children` 和平台返回回调;
48
- 待办 renderer 只使用 `StandardApplicationTodoCenterProps` 的当前用户 items、加载/错误、
49
- 查询、刷新、增量加载、交互和跳转回调。省略该属性继续使用平台默认页面。应用不得接管
50
- `/todos`、`/m/todos`、Workflow 路由、`RuntimeBoundary`、Token 或 Notification Hub API。
35
+ 只检查时运行 `pnpm openxiangda check`;需要发布测试环境时直接运行 `pnpm openxiangda deploy`,它已包含检查、测试和构建。纯前端无需 Docker,启用后端时才构建官方 Dockerfile 镜像。
51
36
 
52
- 生成式资源后台路径固定为 `/admin/resources/<resourceCode>...`,移动后台面为
53
- `/m/admin/resources/<resourceCode>...`;普通根路径和 `/m/...` 产品路径可由显式
54
- `user` route 使用。生成页内部跳转来自编译后的 `adminPages`,不要手写旧根路径、别名或
55
- 重定向。显式 route 与任一生成 route 的动态路径形状重复时,配置编译会直接失败。
37
+ 运行 status/logs 确认平台结果并完成真实角色验收。生产使用 `pnpm openxiangda deploy --environment production --from <成功测试运行ID>`;`--dry-run` 只预览。完整发布、取消、恢复和回滚说明使用 `pnpm openxiangda docs delivery`。
56
38
 
57
- 前端一次读取当前登录用户在当前环境的完整应用角色并集和 capability。应用可在 `perspectives` 中声明工作视角;视角只投影页面、行和字段的读取范围,不改变真实身份,也不收窄新增、编辑、删除、流程与自定义动作权限。标准 Data API 自动识别视角;只有绕过标准 Data API 的自定义 Nest 查询才需要通过 `@CurrentPerspective()` 显式实现同等读取投影。字段默认继承资源 read/create/update;`access` 数组为 all-of,`false` 为明确拒绝,无权字段在提交前从 payload 删除。
39
+ ## MCP
58
40
 
59
41
  ```bash
60
- pnpm openxiangda check
61
- pnpm openxiangda deploy
62
- pnpm openxiangda status
63
- pnpm openxiangda logs
42
+ pnpm exec openxiangda --mcp-stdio --cwd <项目绝对路径>
64
43
  ```
65
44
 
66
- 启用后端时,`deploy` 使用按需生成的 `apps/server/Dockerfile` 自动构建并推送 `linux/amd64` 镜像,再把不可变 digest 写入 AppPackage。纯 CRUD 应用可以保持 backend disabled;复杂事务再启用 Nest
67
-
68
- 业务录入优先使用 `openxiangda/field-kit`,其余 PC 控件使用 `antd`,移动控件使用 `antd-mobile`。应用源码不能直接写原生 input/select/textarea/contentEditable。移动入口放在 `src/mobile/`,或使用 `Mobile*.tsx` / `*.mobile.tsx`,`openxiangda check` 会连同本地共享依赖一起检查。该检查是开发反馈,不添加运行时安全校验。
69
-
70
- 先在 `appspec/app.md` 记录任务页面和角色矩阵,再生成界面。测试只为业务规则和关键风险建立单元/接口用例;实际 PC、移动端的选择、校验、提交、回显、无权操作由浏览器验收,不能用编译通过或接口 200 替代。
45
+ 先读 workspace_context,再按需读取 docs_read contract_describe;升级包后重启连接。登录、创建与长期开发进程继续使用 CLI
@@ -17,7 +17,7 @@ const correctionFields = {
17
17
  async function workflowEntryPlatform(page: Page) {
18
18
  await mockPlatform(page, false, undefined, true);
19
19
  const state = {
20
- admin: true,
20
+ admin: true, instanceStatus: 'approved',
21
21
  record: { id: 'record-1', revision: 8, title: '原业务申请', amount: 28600, decision: '已同意', internalNote: '不得显示', systemValue: '内部标识', attachments: [], richText: '<p>原说明</p>' },
22
22
  complexFields: false, uploads: [] as any[], childQueries: [] as any[], auditReads: 0,
23
23
  children: [
@@ -61,7 +61,7 @@ async function workflowEntryPlatform(page: Page) {
61
61
  if (path.endsWith(`/workflow/records/${resourceCode}/${state.record.id}/detail`)) {
62
62
  const childFields = { name: { label: '品名', type: 'text.short', widget: 'text', ...fieldCapabilities }, quantity: { label: '数量', type: 'number.integer', widget: 'number', ...fieldCapabilities }, detailNote: { label: '仅详情说明', type: 'text.short', widget: 'text', ...fieldCapabilities } };
63
63
  const fields = { ...correctionFields, decision: { label: '审批结论', type: 'text.short', widget: 'readonly', ...fieldCapabilities }, ...(state.complexFields ? { items: { label: '采购明细', type: 'subtable', widget: 'subtable', subtable: { resourceCode: 'purchase-lines', foreignKey: 'purchaseId', orderField: 'sortOrder', maxRows: 20 }, ...fieldCapabilities } } : {}) };
64
- const instance = { id: instanceId, appCode, environmentKey: 'preproduction', status: 'approved', outcome: 'approved', startedAt: '2026-09-06T01:00:00Z', completedAt: '2026-09-06T02:38:00Z', dataRef: { resourceCode, recordId: state.record.id } };
64
+ const instance = { id: instanceId, appCode, environmentKey: 'preproduction', status: state.instanceStatus, outcome: state.instanceStatus === 'approved' ? 'approved' : null, startedAt: '2026-09-06T01:00:00Z', completedAt: state.instanceStatus === 'approved' ? '2026-09-06T02:38:00Z' : null, dataRef: { resourceCode, recordId: state.record.id } };
65
65
  const surface = { schemaVersion: 'openxiangda.workflow-surface/v2', protocolVersion: 'workflow_surface_v2', engineVersion: '2.0', surfaceRevision: 'a'.repeat(64), instanceSequence: 4, instance, task: null, operations: [],
66
66
  detailNavigation: { desktopPath: `/admin/purchases/${state.record.id}`, mobilePath: `/m/admin/purchases/${state.record.id}`, custom: false },
67
67
  presentation: { summary: { title: '采购申请', initiatorDisplayName: '陈晨', departmentDisplayName: '办公室', submittedAt: instance.startedAt }, businessDetail: {
@@ -538,3 +538,19 @@ test('mobile child editing selects form fields while readonly details retain the
538
538
  { operation: 'update', resourceCode: 'purchase-lines', id: 'line-1', expectedRevision: 3, data: { name: '移动明细修改' } },
539
539
  ]);
540
540
  });
541
+
542
+ for (const mobile of [false, true]) {
543
+ test(`${mobile ? 'mobile' : 'desktop'} workflow editing is only offered after completion`, async ({ page }) => {
544
+ const state = await workflowEntryPlatform(page);
545
+ await page.setViewportSize(mobile ? { width: 390, height: 600 } : { width: 1440, height: 900 });
546
+ for (const status of ['running', 'returned', 'approved']) {
547
+ state.instanceStatus = status;
548
+ await page.goto(`/workflow-entry.e2e.html?mode=${mobile ? 'mobile' : 'desktop'}-detail`);
549
+ await expect(page.locator('.oxa-record-detail-header')).toBeVisible();
550
+ await expect(page.locator('.oxa-record-detail-header').getByRole('button', { name: '编辑', exact: true })).toHaveCount(status === 'approved' ? 1 : 0);
551
+ await expect(page.locator('.oxa-record-detail-footer').getByRole('button', { name: /关\s*闭/ })).toHaveCount(0);
552
+ await expect(page.locator('.oxa-workflow-current-node')).toHaveCount(0);
553
+ }
554
+ expect(state.correctionReads).toBe(0);
555
+ });
556
+ }
@@ -816,46 +816,88 @@ test('renders a paged desktop work center from the current-user role union', asy
816
816
  }
817
817
  });
818
818
 
819
- test('a current task handler can send CC with the Surface instance command and multiple directory users', async ({ page }) => {
819
+ for (const mobile of [false, true]) {
820
+ for (const multiple of [false, true]) {
821
+ test(`${mobile ? 'mobile' : 'desktop'} ${multiple ? 'CC' : 'transfer'} uses the standard member picker`, async ({ page }) => {
822
+ await page.setViewportSize(mobile ? { width: 320, height: 480 } : { width: 1440, height: 900 });
820
823
  await mockWorkflow(page);
821
824
  const current = detail();
825
+ const key = multiple ? 'cc' : 'transfer';
826
+ const label = multiple ? '抄送' : '转交';
827
+ const field = multiple ? 'userIds' : 'userId';
822
828
  const cc = {
823
- key: 'cc', kind: 'workflow_command', label: '抄送', group: 'instance_control', audience: 'participant',
829
+ key, kind: 'workflow_command', label, group: 'instance_control', audience: 'participant',
824
830
  placement: 'overflow', emphasis: 'neutral', tone: 'neutral', visible: true, enabled: true,
825
- inputSchema: { type: 'object', additionalProperties: false, required: ['userIds'], properties: {
826
- userIds: { type: 'array', title: '抄送给', minItems: 1, maxItems: 20, uniqueItems: true, items: { type: 'string' } },
831
+ inputSchema: { type: 'object', additionalProperties: false, required: [field], properties: {
832
+ [field]: multiple ? { type: 'array', title: '抄送给', minItems: 1, maxItems: 20, uniqueItems: true, items: { type: 'string' } } : { type: 'string', title: '转交给' },
827
833
  comment: { type: 'string', title: '留言', maxLength: 4000 },
828
834
  } },
829
- uiSchema: { presentation: 'dialog', confirmText: '确认抄送', properties: { userIds: { component: 'user_select', mode: 'multiple' } } },
830
- execute: { method: 'POST', href: `/openxiangda-api/v2/applications/${appCode}/workflow/instances/${instanceId}/commands/cc`, idempotencyRequired: true },
835
+ uiSchema: { presentation: 'dialog', confirmText: `确认${label}`, properties: { [field]: { component: 'user_select', mode: multiple ? 'multiple' : 'single' } } },
836
+ execute: { method: 'POST', href: `/openxiangda-api/v2/applications/${appCode}/workflow/${multiple ? `instances/${instanceId}` : `tasks/${taskId}`}/commands/${key}`, idempotencyRequired: true },
831
837
  refresh: ['surface', 'timeline', 'work_center'],
832
838
  };
833
- const augmented = { ...current, operations: [...current.operations, cc], surface: { ...current.surface, operations: [...current.surface.operations, cc] } };
839
+ const augmented = { ...current, operations: [...current.operations.filter(item => item.key !== key), cc], surface: { ...current.surface, operations: [...current.surface.operations.filter(item => item.key !== key), cc] } };
834
840
  await page.route('**/workflow/tasks/*/detail', route => route.fulfill({ json: envelope(augmented) }));
835
- await page.route('**/directory/users?**', route => route.fulfill({ json: envelope({ items: [{ id: 'cc-user-1', label: '陈老师' }, { id: 'cc-user-2', label: '李老师' }], nextCursor: null }) }));
841
+ await page.route('**/directory/**', route => {
842
+ const tree = new URL(route.request().url()).pathname.endsWith('/tree');
843
+ const items = tree ? [] : ['陈老师', '李老师'].map((label, index) => ({ kind: 'user', id: `cc-user-${index + 1}`, label, selectable: true, snapshot: { value: `cc-user-${index + 1}`, label } }));
844
+ return route.fulfill({ json: envelope({ schemaVersion: 'openxiangda.directory-entry-page/v2', kind: tree ? 'department' : 'user', items, nextCursor: null }) });
845
+ });
836
846
  let writes = 0;
837
- await page.route('**/workflow/instances/*/commands/cc', async route => {
847
+ await page.route(`**/commands/${key}`, async route => {
838
848
  writes += 1;
839
- expect(route.request().postDataJSON()).toMatchObject({ commandToken: current.surface.commandToken, input: { userIds: ['cc-user-1', 'cc-user-2'], comment: '请查阅' } });
849
+ expect(route.request().postDataJSON()).toMatchObject({ commandToken: current.surface.commandToken, input: { [field]: multiple ? ['cc-user-1', 'cc-user-2'] : 'cc-user-1', comment: '请查阅' } });
840
850
  expect(route.request().postDataJSON().idempotencyKey).toBeTruthy();
841
851
  expect(route.request().headers()['x-openxiangda-csrf-token']).toBe('workflow-csrf-1');
842
852
  await route.fulfill({ json: envelope({ status: 'completed', advanced: false, instanceId }) });
843
853
  });
844
- await page.goto(workflowFixtureUrl(`/tasks/${taskId}`));
854
+ await page.goto(workflowFixtureUrl(`${mobile ? '/m' : ''}/tasks/${taskId}`));
855
+ const footer = page.locator('.oxa-record-detail-footer');
856
+ await expect(footer).toBeVisible();
857
+ await expect(footer.getByRole('button', { name: /关\s*闭|编\s*辑/ })).toHaveCount(0);
858
+ if (mobile) {
859
+ const boxes = await footer.locator('.oxa-workflow-actions > button').evaluateAll(elements => elements.map(element => element.getBoundingClientRect().y));
860
+ expect(boxes).toHaveLength(3);
861
+ expect(Math.max(...boxes) - Math.min(...boxes)).toBeLessThan(2);
862
+ }
845
863
  await page.getByRole('button', { name: '更多操作' }).click();
846
- await page.getByRole('button', { name: '抄送', exact: true }).click();
847
- await page.getByRole('button', { name: '确认抄送' }).click();
864
+ await page.getByRole('button', { name: label, exact: true }).click();
865
+ await page.getByRole('button', { name: `确认${label}` }).click();
866
+ expect(writes).toBe(0);
867
+ await expect(page.getByRole('combobox')).toHaveCount(0);
868
+ if (mobile) {
869
+ const bounds = await page.locator('.oxa-workflow-operation-drawer .ant-drawer-content-wrapper').boundingBox();
870
+ expect(bounds!.y).toBeGreaterThanOrEqual(0);
871
+ expect(bounds!.y + bounds!.height).toBeLessThanOrEqual(481);
872
+ await expect(page.getByRole('button', { name: `确认${label}` })).toBeInViewport();
873
+ }
874
+ const trigger = page.locator(mobile ? '.oxa-mobile-choice-field button' : '.oxa-directory-trigger').first();
875
+ await trigger.click();
876
+ if (mobile) {
877
+ await expect(page.locator('.oxa-mobile-selection-sheet')).toBeInViewport();
878
+ await expect(page.getByRole('button', { name: '关闭', exact: true }).last()).toBeInViewport();
879
+ await expect(page.getByRole('button', { name: '确定', exact: true })).toBeInViewport();
880
+ }
881
+ await page.getByPlaceholder(mobile ? /搜索/ : '搜索成员姓名或工号').fill('老师');
882
+ await page.getByText('陈老师', { exact: true }).click();
883
+ await page.getByRole('button', { name: mobile ? '关闭' : /取\s*消/, exact: true }).last().click();
884
+ await page.getByRole('button', { name: `确认${label}` }).click();
848
885
  expect(writes).toBe(0);
849
- const select = page.getByRole('dialog').getByRole('combobox');
850
- await select.fill('老师');
851
- await page.getByTitle('陈老师', { exact: true }).click();
852
- await page.getByTitle('李老师', { exact: true }).click();
886
+ await trigger.click();
887
+ await page.getByPlaceholder(mobile ? /搜索/ : '搜索成员姓名或工号').fill('老师');
888
+ await page.getByText('陈老师', { exact: true }).click();
889
+ if (multiple) await page.getByText('李老师', { exact: true }).click();
890
+ await page.getByRole('button', { name: mobile ? `确定(${multiple ? 2 : 1})` : /确\s*定/, exact: true }).last().click();
853
891
  await page.getByLabel('留言').fill('请查阅');
854
- await page.getByRole('button', { name: '确认抄送' }).click();
892
+ await page.getByRole('button', { name: `确认${label}` }).click();
855
893
  await expect.poll(() => writes).toBe(1);
856
894
  await expect(page.getByRole('button', { name: /同\s*意/ })).toBeVisible();
857
895
  });
858
896
 
897
+ }
898
+
899
+ }
900
+
859
901
  test('renders the generic desktop and mobile application todo center without a second router', async ({
860
902
  page,
861
903
  }) => {
@@ -14,7 +14,7 @@
14
14
  "@ant-design/icons": "6.2.3",
15
15
  "@refinedev/core": "5.0.12",
16
16
  "antd": "6.4.3",
17
- "openxiangda": "2.0.0-alpha.104",
17
+ "openxiangda": "2.0.0-alpha.106",
18
18
  "react": "19.2.8",
19
19
  "react-dom": "19.2.8",
20
20
  "react-router-dom": "7.8.2"
@@ -22,7 +22,7 @@
22
22
  "build": "pnpm --recursive build"
23
23
  },
24
24
  "devDependencies": {
25
- "openxiangda": "2.0.0-alpha.104",
25
+ "openxiangda": "2.0.0-alpha.106",
26
26
  "typescript": "5.9.3"
27
27
  }
28
28
  }