openxiangda 1.0.266 → 1.0.268

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +12 -7
  3. package/lib/cli.js +30 -13
  4. package/lib/generation-update.js +42 -0
  5. package/lib/skills.js +57 -62
  6. package/openxiangda-skills/SKILL.md +5 -3
  7. package/openxiangda-skills/references/openxiangda-api.md +1 -1
  8. package/openxiangda-skills/references/resource-manifest-cheatsheet.md +1 -1
  9. package/openxiangda-skills/references/workspace-state.md +2 -2
  10. package/package.json +52 -3
  11. package/templates/openxiangda-react-spa/app-workspace.config.ts +1 -1
  12. package/templates/sy-lowcode-app-workspace/AGENTS.md +1 -1
  13. package/templates/sy-lowcode-app-workspace/app-workspace.config.ts +1 -1
  14. package/v2/README.md +0 -35
  15. package/v2/skills/manifest.json +0 -45
  16. package/v2/skills/openxiangda-v1-maintenance/SKILL.md +0 -21
  17. package/v2/skills/openxiangda-v1-maintenance/agents/openai.yaml +0 -4
  18. package/v2/skills/openxiangda-v2/SKILL.md +0 -38
  19. package/v2/skills/openxiangda-v2/agents/openai.yaml +0 -4
  20. package/v2/skills/openxiangda-v2-architecture/SKILL.md +0 -29
  21. package/v2/skills/openxiangda-v2-architecture/agents/openai.yaml +0 -4
  22. package/v2/skills/openxiangda-v2-backend/SKILL.md +0 -28
  23. package/v2/skills/openxiangda-v2-backend/agents/openai.yaml +0 -4
  24. package/v2/skills/openxiangda-v2-data-authz/SKILL.md +0 -28
  25. package/v2/skills/openxiangda-v2-data-authz/agents/openai.yaml +0 -4
  26. package/v2/skills/openxiangda-v2-delivery/SKILL.md +0 -30
  27. package/v2/skills/openxiangda-v2-delivery/agents/openai.yaml +0 -4
  28. package/v2/skills/openxiangda-v2-frontend/SKILL.md +0 -21
  29. package/v2/skills/openxiangda-v2-frontend/agents/openai.yaml +0 -4
  30. package/v2/skills/openxiangda-v2-workflow-events/SKILL.md +0 -28
  31. package/v2/skills/openxiangda-v2-workflow-events/agents/openai.yaml +0 -4
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 OpenXiangda contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -4,18 +4,23 @@
4
4
 
5
5
  OpenXiangda is a lightweight CLI and skill package for private low-code platforms.
6
6
 
7
- ## Two runtime generations
7
+ ## Repository boundary
8
8
 
9
- OpenXiangda now has two deliberately separate development tracks:
9
+ This repository contains only the stable OpenXiangda 1.x maintenance toolchain.
10
+ It maintains existing resource-based applications and its legacy Delivery V2
11
+ protocol. Stable applications keep this runtime and are not migrated by a
12
+ platform upgrade.
10
13
 
11
- - `openxiangda` 1.x maintains existing resource-based applications and its legacy Delivery V2 protocol. Stable applications keep this runtime and are not migrated by a platform upgrade.
12
- - `v2/` contains the new platform-2.0 application toolchain: `create-openxiangda`, `@openxiangda/cli`, `@openxiangda/mcp`, standard React/NestJS packages, typed configuration, domain skills, and application-level deployment.
13
-
14
- For a new 2.0 application, start with [`v2/docs/getting-started.md`](v2/docs/getting-started.md). A 2.0 workspace has `openxiangda.config.ts`, `apps/web`, and `apps/server`; it must not use the 1.x resource/SDD publishing commands.
14
+ OpenXiangda 2.0 is developed and released from the independent
15
+ `tools/openxiangda-v2` repository pinned by the platform orchestration
16
+ repository. A new 2.0 workspace must use that repository's current public
17
+ packages, unified AI skill, templates, and documentation. It must not use the
18
+ 1.x resource/SDD publishing commands or any historical embedded copy of the
19
+ 2.0 toolchain.
15
20
 
16
21
  Normal OpenXiangda app development uses platform-user login tokens through `/openxiangda-api/v1`; it does not use AK/SK. External backend and third-party integrations use the separate `openxiangda-open-api` skill, `/dingtalk-api/v1.0`, and a platform-managed AK/SK credential.
17
22
 
18
- Private platform routing is fixed: backend APIs are under `/service`, platform management is under `/platform`, and app runtime access is under `/view`. Passing a root domain such as `https://yida.wisejob.cn/` to the CLI is supported; OpenXiangda stores the API base as `https://yida.wisejob.cn/service`.
23
+ Private platform routing is fixed: backend APIs are under `/service`, platform management is under `/platform`, and app runtime access is under `/view`. Passing a root domain such as `https://platform.example.com/` to the CLI is supported; OpenXiangda stores the API base as `https://platform.example.com/service`.
19
24
 
20
25
  ## OpenXiangda 1.x Delivery V2 (maintenance)
21
26
 
package/lib/cli.js CHANGED
@@ -114,6 +114,7 @@ const {
114
114
  summarizeBindingDifferences,
115
115
  } = require('./resource-binding-contract');
116
116
  const { getSkillStatusReport, installSkills } = require('./skills');
117
+ const { resolveUpdateTarget, buildGenerationUpdateCommand } = require('./generation-update');
117
118
  const {
118
119
  assertOrClaimWorktreeOwner,
119
120
  claimWorktreeOwner,
@@ -532,9 +533,10 @@ async function update(args) {
532
533
  return;
533
534
  }
534
535
  const registry = normalizeNpmRegistry(flags.registry || OFFICIAL_NPM_REGISTRY);
536
+ const selection = resolveUpdateTarget({ target: flags.target });
535
537
 
536
538
  if (requestedSubcommand === 'check') {
537
- const result = checkOpenXiangdaUpdate(registry);
539
+ const result = checkOpenXiangdaUpdate(registry, selection);
538
540
  if (flags.json) return writeJson(result);
539
541
  printUpdateCheck(result);
540
542
  return;
@@ -545,6 +547,7 @@ async function update(args) {
545
547
  json: Boolean(flags.json),
546
548
  skipSkills: Boolean(flags['no-skills']),
547
549
  timeoutSeconds: flags['timeout-seconds'],
550
+ ...selection,
548
551
  });
549
552
  if (flags.json) return writeJson(result);
550
553
  print('OpenXiangda 已更新。');
@@ -562,8 +565,8 @@ function normalizeNpmRegistry(value) {
562
565
  return registry.replace(/\/+$/, '') || OFFICIAL_NPM_REGISTRY;
563
566
  }
564
567
 
565
- function checkOpenXiangdaUpdate(registry) {
566
- const latestVersion = fetchLatestOpenXiangdaVersion(registry);
568
+ function checkOpenXiangdaUpdate(registry, selection = resolveUpdateTarget()) {
569
+ const latestVersion = fetchLatestOpenXiangdaVersion(registry, selection.channel);
567
570
  const versionComparison = compareVersions(latestVersion, CURRENT_VERSION);
568
571
  const updateAvailable = versionComparison > 0;
569
572
  return {
@@ -577,8 +580,10 @@ function checkOpenXiangdaUpdate(registry) {
577
580
  : versionComparison < 0
578
581
  ? 'local_newer_than_registry'
579
582
  : 'latest',
580
- installCommand: `npm ${buildOpenXiangdaUpdateInstallPlan(registry).args.join(' ')}`,
581
- skillInstallCommand: 'openxiangda skill install --force',
583
+ target: selection.target,
584
+ channel: selection.channel,
585
+ installCommand: `openxiangda update install --target ${selection.target}`,
586
+ skillInstallCommand: 'openxiangda skill install',
582
587
  compatibilityCheckCommand: 'openxiangda commands --json',
583
588
  checkedAt: new Date().toISOString(),
584
589
  notes: [
@@ -588,10 +593,10 @@ function checkOpenXiangdaUpdate(registry) {
588
593
  };
589
594
  }
590
595
 
591
- function fetchLatestOpenXiangdaVersion(registry) {
596
+ function fetchLatestOpenXiangdaVersion(registry, channel = 'v1') {
592
597
  const result = spawnSync(
593
598
  'npm',
594
- ['view', `${NPM_PACKAGE_NAME}@latest`, 'version', `--registry=${registry}`, '--json'],
599
+ ['view', `${NPM_PACKAGE_NAME}@${channel}`, 'version', `--registry=${registry}`, '--json'],
595
600
  {
596
601
  encoding: 'utf8',
597
602
  timeout: 30000,
@@ -630,17 +635,22 @@ function normalizeUpdateInstallTimeoutSeconds(value) {
630
635
 
631
636
  function buildOpenXiangdaUpdateInstallPlan(registryInput, options = {}) {
632
637
  const registry = normalizeNpmRegistry(registryInput);
638
+ const selection = resolveUpdateTarget(options);
639
+ const version = options.version || fetchLatestOpenXiangdaVersion(registry, selection.channel);
640
+ const execution = buildGenerationUpdateCommand(selection, version);
633
641
  const timeoutSeconds = normalizeUpdateInstallTimeoutSeconds(
634
642
  options.timeoutSeconds
635
643
  );
636
644
  return {
637
645
  registry,
638
646
  timeoutSeconds,
647
+ ...selection,
648
+ command: execution.command,
649
+ version,
639
650
  args: [
640
- 'install',
641
- '-g',
642
- `${NPM_PACKAGE_NAME}@latest`,
651
+ ...execution.args,
643
652
  `--registry=${registry}`,
653
+ ...(execution.command === 'npm' ? [
644
654
  '--prefer-offline',
645
655
  '--legacy-peer-deps',
646
656
  '--no-audit',
@@ -650,6 +660,7 @@ function buildOpenXiangdaUpdateInstallPlan(registryInput, options = {}) {
650
660
  '--fetch-timeout=60000',
651
661
  '--fetch-retry-mintimeout=1000',
652
662
  '--fetch-retry-maxtimeout=10000',
663
+ ] : []),
653
664
  ],
654
665
  };
655
666
  }
@@ -662,6 +673,7 @@ async function runCommandWithHeartbeat(command, args, options = {}) {
662
673
  let child;
663
674
  try {
664
675
  child = spawn(command, args, {
676
+ cwd: options.cwd || process.cwd(),
665
677
  encoding: 'utf8',
666
678
  stdio: quiet ? ['ignore', 'pipe', 'pipe'] : 'inherit',
667
679
  env: options.env || process.env,
@@ -731,7 +743,8 @@ async function installOpenXiangdaUpdate(registry, options = {}) {
731
743
  if (!quiet) {
732
744
  print(`执行: npm ${npmArgs.join(' ')}`);
733
745
  }
734
- const installResult = await runCommandWithHeartbeat('npm', npmArgs, {
746
+ const installResult = await runCommandWithHeartbeat(plan.command, npmArgs, {
747
+ cwd: plan.cwd,
735
748
  quiet,
736
749
  timeoutMs: plan.timeoutSeconds * 1000,
737
750
  env: { ...process.env, npm_config_registry: plan.registry },
@@ -763,11 +776,15 @@ async function installOpenXiangdaUpdate(registry, options = {}) {
763
776
  },
764
777
  };
765
778
 
766
- if (!options.skipSkills) {
779
+ if (!options.skipSkills && plan.target === 'workspace') {
767
780
  if (!quiet) {
768
781
  print('刷新 OpenXiangda skills: openxiangda skill install --force');
769
782
  }
770
- const skillResult = spawnSync('openxiangda', ['skill', 'install', '--force'], {
783
+ const localManifest = path.join(plan.cwd, 'node_modules/openxiangda/package.json');
784
+ const localPackage = JSON.parse(fs.readFileSync(localManifest, 'utf8'));
785
+ const localBin = path.resolve(path.dirname(localManifest), typeof localPackage.bin === 'string' ? localPackage.bin : localPackage.bin.openxiangda);
786
+ const skillResult = spawnSync(process.execPath, [localBin, 'skill', 'install'], {
787
+ cwd: plan.cwd,
771
788
  encoding: 'utf8',
772
789
  stdio: quiet ? 'pipe' : 'inherit',
773
790
  timeout: 60000,
@@ -0,0 +1,42 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ function resolveUpdateTarget(options = {}) {
5
+ let root = path.resolve(options.cwd || process.cwd());
6
+ let workspace = null;
7
+ while (true) {
8
+ const v1 = fs.existsSync(path.join(root, 'app-workspace.config.ts')) || fs.existsSync(path.join(root, '.openxiangda/state.json'));
9
+ const v2 = fs.existsSync(path.join(root, 'openxiangda.config.ts')) || fs.existsSync(path.join(root, 'openxiangda-app.config.ts'));
10
+ if (v1 && v2) throw new Error('WORKSPACE_GENERATION_CONFLICT: 同一目录存在 V1/V2 工作区标记');
11
+ if (v2) throw new Error('WORKSPACE_ENGINE_GENERATION_MISMATCH: V1 CLI 不能升级 V2 项目;请使用统一入口');
12
+ if (v1) { workspace = root; break; }
13
+ const parent = path.dirname(root);
14
+ if (parent === root) break;
15
+ root = parent;
16
+ }
17
+ const target = options.target || (workspace ? 'workspace' : 'launcher');
18
+ if (!['workspace', 'launcher'].includes(target)) throw new Error('DISTRIBUTION_UPDATE_TARGET_INVALID: 使用 workspace 或 launcher');
19
+ if (target === 'workspace' && !workspace) throw new Error('DISTRIBUTION_WORKSPACE_REQUIRED: 未找到 V1 工作区');
20
+ return { target, channel: target === 'workspace' ? 'legacy-v1' : 'latest', cwd: workspace || process.cwd() };
21
+ }
22
+
23
+ function buildGenerationUpdateCommand(selection, version) {
24
+ if (!/^[12]\.\d+\.\d+$/.test(version)) throw new Error('DISTRIBUTION_UPDATE_VERSION_INVALID: 升级目标必须是已发布的稳定版本');
25
+ if (selection.target === 'launcher') {
26
+ if (!version.startsWith('2.')) throw new Error('DISTRIBUTION_UPDATE_GENERATION_MISMATCH: 全局入口需要 V2');
27
+ if (Number(process.versions.node.split('.')[0]) < 24) throw new Error('DISTRIBUTION_NODE_VERSION_REQUIRED: 全局统一入口需要 Node.js 24;当前 V1 项目环境不会自动改变');
28
+ return { command: 'npm', args: ['install', '-g', `openxiangda@${version}`] };
29
+ }
30
+ if (!version.startsWith('1.')) throw new Error('DISTRIBUTION_UPDATE_GENERATION_MISMATCH: V1 项目只允许安装 V1');
31
+ const file = path.join(selection.cwd, 'package.json');
32
+ if (!fs.existsSync(file)) throw new Error('DISTRIBUTION_PACKAGE_MANIFEST_REQUIRED: 工作区缺少 package.json');
33
+ const manifest = JSON.parse(fs.readFileSync(file, 'utf8'));
34
+ const pnpm = fs.existsSync(path.join(selection.cwd, 'pnpm-lock.yaml')) || manifest.packageManager?.startsWith('pnpm@');
35
+ if (pnpm && fs.existsSync(path.join(selection.cwd, 'package-lock.json'))) throw new Error('DISTRIBUTION_PACKAGE_MANAGER_CONFLICT: 多个包管理器锁文件');
36
+ if (fs.existsSync(path.join(selection.cwd, 'yarn.lock'))) throw new Error('DISTRIBUTION_PACKAGE_MANAGER_UNSUPPORTED: 请通过项目 Yarn 命令显式安装 openxiangda@legacy-v1');
37
+ return { command: pnpm ? 'pnpm' : 'npm', args: pnpm
38
+ ? ['add', ...(manifest.dependencies?.openxiangda ? [] : ['--save-dev']), '--save-exact', `openxiangda@${version}`, ...(fs.existsSync(path.join(selection.cwd, 'pnpm-workspace.yaml')) ? ['--workspace-root'] : [])]
39
+ : ['install', manifest.dependencies?.openxiangda ? '--save-prod' : '--save-dev', '--save-exact', `openxiangda@${version}`] };
40
+ }
41
+
42
+ module.exports = { resolveUpdateTarget, buildGenerationUpdateCommand };
package/lib/skills.js CHANGED
@@ -11,9 +11,9 @@ const MANAGER = 'openxiangda';
11
11
 
12
12
  const SKILL_SPECS = [
13
13
  {
14
- name: 'openxiangda',
15
- displayName: 'OpenXiangda',
16
- shortDescription: '私有化低代码平台 CLI 与 AI skill 入口。',
14
+ name: 'openxiangda-v1',
15
+ displayName: 'OpenXiangda V1',
16
+ shortDescription: 'OpenXiangda V1 维护入口,仅用于 V1 工作区。',
17
17
  sourceRelativePath: 'openxiangda-skills',
18
18
  type: 'root',
19
19
  },
@@ -82,64 +82,11 @@ const SKILL_SPECS = [
82
82
  sourceRelativePath: 'openxiangda-skills/skills/openxiangda-open-api',
83
83
  type: 'subskill',
84
84
  },
85
- {
86
- name: 'openxiangda-v2',
87
- displayName: 'OpenXiangda 2.0',
88
- shortDescription: '标准 React/NestJS 应用与应用级交付入口。',
89
- sourceRelativePath: 'v2/skills/openxiangda-v2',
90
- type: 'subskill',
91
- },
92
- {
93
- name: 'openxiangda-v2-architecture',
94
- displayName: 'OpenXiangda 2.0 Architecture',
95
- shortDescription: '设计 2.0 应用边界与类型化平台契约。',
96
- sourceRelativePath: 'v2/skills/openxiangda-v2-architecture',
97
- type: 'subskill',
98
- },
99
- {
100
- name: 'openxiangda-v2-frontend',
101
- displayName: 'OpenXiangda 2.0 Frontend',
102
- shortDescription: '开发 React、Ant Design 与标准后台页面。',
103
- sourceRelativePath: 'v2/skills/openxiangda-v2-frontend',
104
- type: 'subskill',
105
- },
106
- {
107
- name: 'openxiangda-v2-backend',
108
- displayName: 'OpenXiangda 2.0 Backend',
109
- shortDescription: '开发平台托管的标准 NestJS 应用后端。',
110
- sourceRelativePath: 'v2/skills/openxiangda-v2-backend',
111
- type: 'subskill',
112
- },
113
- {
114
- name: 'openxiangda-v2-data-authz',
115
- displayName: 'OpenXiangda 2.0 Data and AuthZ',
116
- shortDescription: '设计 Data API、RBAC 与上下文数据权限。',
117
- sourceRelativePath: 'v2/skills/openxiangda-v2-data-authz',
118
- type: 'subskill',
119
- },
120
- {
121
- name: 'openxiangda-v2-workflow-events',
122
- displayName: 'OpenXiangda 2.0 Workflow and Events',
123
- shortDescription: '开发 Workflow Kernel v2 与持久事件消费者。',
124
- sourceRelativePath: 'v2/skills/openxiangda-v2-workflow-events',
125
- type: 'subskill',
126
- },
127
- {
128
- name: 'openxiangda-v2-delivery',
129
- displayName: 'OpenXiangda 2.0 Delivery',
130
- shortDescription: '构建、部署、观察、晋级和回滚完整应用。',
131
- sourceRelativePath: 'v2/skills/openxiangda-v2-delivery',
132
- type: 'subskill',
133
- },
134
- {
135
- name: 'openxiangda-v1-maintenance',
136
- displayName: 'OpenXiangda 1.x Maintenance',
137
- shortDescription: '不迁移地安全维护稳定 1.x 应用。',
138
- sourceRelativePath: 'v2/skills/openxiangda-v1-maintenance',
139
- type: 'subskill',
140
- },
141
85
  ];
142
86
 
87
+ // V1 does not own V2 or the unified routing skill, including historical installs.
88
+ const RETIRED_SKILL_SPECS = [];
89
+
143
90
  function getDefaultCodexSkillsDir(env = process.env) {
144
91
  const codexHome = env.CODEX_HOME || path.join(os.homedir(), '.codex');
145
92
  return path.join(codexHome, 'skills');
@@ -242,20 +189,52 @@ function getSkillStatus(spec, skillsDir) {
242
189
  };
243
190
  }
244
191
 
192
+ function getRetiredSkillStatus(spec, skillsDir) {
193
+ const targetDir = path.join(skillsDir, spec.name);
194
+ if (!fs.existsSync(targetDir)) {
195
+ return {
196
+ name: spec.name,
197
+ status: 'absent',
198
+ targetDir,
199
+ sourceRelativePath: spec.sourceRelativePath,
200
+ };
201
+ }
202
+
203
+ const manifest = readManifest(targetDir);
204
+ const isManagedRetiredSkill =
205
+ manifest?.manager === MANAGER &&
206
+ manifest.sourceRelativePath === spec.sourceRelativePath;
207
+ return {
208
+ name: spec.name,
209
+ status: isManagedRetiredSkill ? 'retired-managed' : 'preserved-external',
210
+ targetDir,
211
+ sourceRelativePath: spec.sourceRelativePath,
212
+ };
213
+ }
214
+
215
+ function removeRetiredManagedSkill(spec, skillsDir) {
216
+ const status = getRetiredSkillStatus(spec, skillsDir);
217
+ if (status.status === 'retired-managed') {
218
+ fs.rmSync(status.targetDir, { recursive: true, force: true });
219
+ }
220
+ }
221
+
245
222
  function getSkillStatusReport(options = {}) {
246
223
  const agent = validateAgent(options.agent);
247
224
  const env = options.env || process.env;
248
225
 
249
226
  // 获取目标目录列表
250
- const skillsDirs = getDualSkillsDirs(agent, env);
227
+ const skillsDirs = options.dest ? [path.resolve(options.dest)] : getDualSkillsDirs(agent, env);
251
228
 
252
229
  const results = [];
253
230
  for (const skillsDir of skillsDirs) {
254
231
  const skills = SKILL_SPECS.map(spec => getSkillStatus(spec, skillsDir));
232
+ const retiredSkills = RETIRED_SKILL_SPECS.map(spec => getRetiredSkillStatus(spec, skillsDir));
255
233
  results.push({
256
234
  agent,
257
235
  skillsDir,
258
236
  skills,
237
+ retiredSkills,
259
238
  });
260
239
  }
261
240
 
@@ -278,11 +257,12 @@ function installSkills(options = {}) {
278
257
  const force = Boolean(options.force);
279
258
 
280
259
  // 获取目标目录列表
281
- const skillsDirs = getDualSkillsDirs(agent, options.env);
260
+ const skillsDirs = options.dest ? [path.resolve(options.dest)] : getDualSkillsDirs(agent, options.env);
282
261
 
283
262
  const results = [];
284
263
  for (const skillsDir of skillsDirs) {
285
264
  const before = SKILL_SPECS.map(spec => getSkillStatus(spec, skillsDir));
265
+ const retiredBefore = RETIRED_SKILL_SPECS.map(spec => getRetiredSkillStatus(spec, skillsDir));
286
266
  const conflicts = before.filter(item => item.status === 'foreign');
287
267
 
288
268
  if (conflicts.length > 0 && !force && !dryRun) {
@@ -298,17 +278,29 @@ function installSkills(options = {}) {
298
278
  targetDir: item.targetDir,
299
279
  sourceRelativePath: item.sourceRelativePath,
300
280
  }));
281
+ const retiredOperations = retiredBefore.map(item => ({
282
+ name: item.name,
283
+ operation: item.status === 'retired-managed' ? 'remove-retired-managed' : 'preserve',
284
+ targetDir: item.targetDir,
285
+ sourceRelativePath: item.sourceRelativePath,
286
+ }));
301
287
 
302
288
  if (!dryRun) {
303
289
  fs.mkdirSync(skillsDir, { recursive: true });
304
290
  for (const spec of SKILL_SPECS) {
305
291
  installOneSkill(spec, skillsDir);
306
292
  }
293
+ for (const spec of RETIRED_SKILL_SPECS) {
294
+ removeRetiredManagedSkill(spec, skillsDir);
295
+ }
307
296
  }
308
297
 
309
298
  const after = dryRun
310
299
  ? before
311
300
  : SKILL_SPECS.map(spec => getSkillStatus(spec, skillsDir));
301
+ const retiredAfter = dryRun
302
+ ? retiredBefore
303
+ : RETIRED_SKILL_SPECS.map(spec => getRetiredSkillStatus(spec, skillsDir));
312
304
 
313
305
  results.push({
314
306
  agent,
@@ -317,7 +309,9 @@ function installSkills(options = {}) {
317
309
  dryRun,
318
310
  force,
319
311
  operations,
312
+ retiredOperations,
320
313
  skills: after,
314
+ retiredSkills: retiredAfter,
321
315
  });
322
316
  }
323
317
 
@@ -408,7 +402,7 @@ function writeAgentMetadata(spec, skillDir) {
408
402
  const defaultPrompt =
409
403
  spec.defaultPrompt ||
410
404
  (spec.name === 'openxiangda'
411
- ? '使用 $openxiangda 处理私有化低代码平台的登录、发布和诊断任务。'
405
+ ? '使用 $openxiangda-v1 处理 V1 工作区的登录、发布和诊断任务。'
412
406
  : `使用 $${spec.name} 处理对应的 OpenXiangda 低代码平台任务。`);
413
407
  const content = [
414
408
  'interface:',
@@ -446,6 +440,7 @@ function buildWarnings(legacySkills) {
446
440
 
447
441
  module.exports = {
448
442
  INSTALL_MANIFEST,
443
+ RETIRED_SKILL_SPECS,
449
444
  SKILL_SPECS,
450
445
  getSkillStatusReport,
451
446
  installSkills,
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: openxiangda
3
- description: "Use OpenXiangda for private low-code platform work: app workspaces, forms, pages, resources, functions, automations, workflows, permissions, publishing, deployment, diagnosis, profiles, and the openxiangda CLI."
2
+ name: openxiangda-v1
3
+ description: "Maintain existing OpenXiangda V1 workspaces: forms, pages, resources, workflows, permissions, publishing and diagnosis. New applications default to V2; assess V2 adoption for V1 projects still in testing when capability coverage and migration cost permit."
4
4
  ---
5
5
 
6
6
  <!-- OpenXiangda-Policy-Version: 7 -->
@@ -13,10 +13,12 @@ This file is a router and safety card. Read only the one or two subskills select
13
13
 
14
14
  ## Select the runtime generation first
15
15
 
16
- If the workspace contains `openxiangda.config.ts`, `apps/web`, and `apps/server`, it is a platform-2.0 application. Stop this 1.x resource flow and use `$openxiangda-v2` plus its architecture, frontend, backend, data-authz, workflow-events, and delivery skills. The 2.0 CLI operates on one immutable application package and does not use SDD or per-resource publishing.
16
+ If the nearest workspace contains `openxiangda.config.ts` or `openxiangda-app.config.ts`, it is a platform-2.0 application; a Nest server is optional. Stop this 1.x resource flow and use the independently released `$openxiangda-v2` skill. The 2.0 CLI operates on one immutable application package and does not use SDD or per-resource publishing.
17
17
 
18
18
  If the workspace contains `app-workspace.config.ts`, forms/pages/resource manifests, or an existing 1.x state directory, continue with this router. Never migrate a stable 1.x application merely because platform 2.0 is available.
19
19
 
20
+ For an existing V1 project, proactively check whether V2 covers its required capabilities, whether it is still in testing, and whether migration cost is manageable. When those conditions hold, recommend V2 first and explain the benefit, rebuild scope and verification cost. Use the unified entry's `openxiangda migrate assess --to v2` for source pointers; confirm the project design, data/workflow mapping, acceptance and rollback before implementing migration. Keep unknown conditions explicit and continue current maintenance with the matching engine until migration is authorized.
21
+
20
22
  ## 1.x Delivery V2 is the normal 1.x release path
21
23
 
22
24
  When `app-workspace.config.ts` declares `deliveryVersion: 2`, all later V1 SDD,
@@ -930,7 +930,7 @@ Body:
930
930
  "allowedExtensions": ["txt", "pdf", "png"],
931
931
  "cors": {
932
932
  "managed": true,
933
- "allowedOrigins": ["https://yida.wisejob.cn"],
933
+ "allowedOrigins": ["https://platform.example.com"],
934
934
  "allowedMethods": ["PUT", "GET", "HEAD"],
935
935
  "allowedHeaders": ["content-type", "x-oss-*"],
936
936
  "exposeHeaders": ["ETag", "x-oss-request-id"],
@@ -173,7 +173,7 @@ await auth.phoneCodeLogin({ phone, code, challengeId: sent.challengeId });
173
173
  "allowedExtensions": ["txt", "pdf", "png"],
174
174
  "cors": {
175
175
  "managed": true,
176
- "allowedOrigins": ["https://yida.wisejob.cn"],
176
+ "allowedOrigins": ["https://platform.example.com"],
177
177
  "allowedMethods": ["PUT", "GET", "HEAD"],
178
178
  "allowedHeaders": ["content-type", "x-oss-*"],
179
179
  "exposeHeaders": ["ETag", "x-oss-request-id"],
@@ -64,7 +64,7 @@ Environment-managed workspaces add a logical application and target-specific bin
64
64
  "currentTarget": "preproduction",
65
65
  "targets": {
66
66
  "preproduction": {
67
- "profile": "hgy",
67
+ "profile": "instrument-example",
68
68
  "environmentId": "PRE_ENV_UUID",
69
69
  "kind": "preproduction",
70
70
  "appType": "APP_PRE",
@@ -82,7 +82,7 @@ Environment-managed workspaces add a logical application and target-specific bin
82
82
  "resources": {}
83
83
  },
84
84
  "production": {
85
- "profile": "hgy",
85
+ "profile": "instrument-example",
86
86
  "environmentId": "PROD_ENV_UUID",
87
87
  "kind": "production",
88
88
  "appType": "APP_PROD",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.266",
3
+ "version": "1.0.268",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {
@@ -55,7 +55,6 @@
55
55
  "bin/",
56
56
  "lib/",
57
57
  "openxiangda-skills/",
58
- "v2/skills/",
59
58
  "policy/",
60
59
  "templates/",
61
60
  "packages/sdk/bin/",
@@ -216,8 +215,58 @@
216
215
  "node": ">=18"
217
216
  },
218
217
  "publishConfig": {
218
+ "tag": "legacy-v1",
219
219
  "access": "public",
220
220
  "registry": "https://registry.npmjs.org/"
221
221
  },
222
- "license": "MIT"
222
+ "license": "MIT",
223
+ "repository": {
224
+ "type": "git",
225
+ "url": "git+https://github.com/1377385356/openxiangda-v1.git"
226
+ },
227
+ "homepage": "https://github.com/1377385356/openxiangda-v1",
228
+ "bugs": {
229
+ "url": "https://github.com/1377385356/openxiangda-v1/issues"
230
+ },
231
+ "openxiangdaRelease": {
232
+ "schemaVersion": "openxiangda.release-notes/v1",
233
+ "version": "1.0.268",
234
+ "title": "OpenXiangda V1 维护版 1.0.268",
235
+ "status": "reviewed",
236
+ "summary": "旧项目继续使用 V1 引擎,项目升级保持在 V1 维护渠道;同时兼容新的全局统一入口与独立的 V2 Skill。",
237
+ "newFeatures": [
238
+ "V1 工具源码从经审查的公开基线发布到独立 GitHub 仓库,并提供对应版本说明。"
239
+ ],
240
+ "fixes": [
241
+ "在 V1 项目内执行 update 默认更新项目依赖,使用 v1 维护渠道并固定具体版本。",
242
+ "全局入口更新单独使用 --target launcher,检查 Node.js 24 要求并安装统一 V2 入口。",
243
+ "V1 主 Skill 使用 openxiangda-v1 名称,安装时保留统一入口和 V2 技能。",
244
+ "V1 发布仅允许 legacy-v1 渠道,防止维护版覆盖 V2 的 latest。"
245
+ ],
246
+ "affectedUsers": [
247
+ "维护既有 V1 项目的开发者",
248
+ "已经安装全局统一入口的 V1 用户"
249
+ ],
250
+ "compatibility": {
251
+ "node": ">=18;全局 V2 统一入口需要 >=24",
252
+ "workspaceGenerations": [
253
+ "v1"
254
+ ],
255
+ "workspacePolicy": "沿用现有 app-workspace.config.ts、平台绑定、登录态、业务数据及流程。",
256
+ "platformPolicy": "本次维护不改变平台协议或部署状态。"
257
+ },
258
+ "upgradeSteps": [
259
+ "项目依赖通过 v1 维护渠道升级,例如 npm install --save-dev --save-exact openxiangda@1.0.268;按项目实际包管理器和依赖类型调整。",
260
+ "安装全局 V2 统一入口后,进入旧项目运行 openxiangda version --json 核对 V1 引擎来源。",
261
+ "刷新对应项目的 V1 Skill,检查依赖与锁文件差异,并执行原有项目测试。",
262
+ "V2 能力满足、项目仍在测试阶段且迁移成本可控时,优先建议 V1 项目采用 V2;先完成项目评估、设计确认和迁移验收。"
263
+ ],
264
+ "knownLimitations": [
265
+ "本版本不会自动把 V1 应用迁移到 V2;跨代迁移需要独立设计、映射、演练和批准。",
266
+ "既有 1.0.267 及更早版本的全局更新命令可能安装 latest;新统一入口仍按旧项目标记调用 V1 引擎。"
267
+ ],
268
+ "issues": [],
269
+ "sha256": "7aaa99d31b91f725b785259031daaeaf3841cb18a95f6155e43009f1f601e6c9",
270
+ "url": "https://github.com/1377385356/openxiangda-v1/releases/tag/v1.0.268"
271
+ }
223
272
  }
@@ -8,7 +8,7 @@ export default defineAppWorkspaceConfig({
8
8
  platformUrl:
9
9
  process.env.APP_PLATFORM_URL ||
10
10
  process.env.OPENXIANGDA_BASE_URL ||
11
- "https://yida.wisejob.cn/service",
11
+ "https://platform.example.com/service",
12
12
  servicePrefix: process.env.APP_SERVICE_PREFIX || "/service",
13
13
  appKey: process.env.APP_KEY || "",
14
14
  appSecret: process.env.APP_SECRET || "",
@@ -139,7 +139,7 @@ sy-lowcode-app-workspace/
139
139
 
140
140
  ## 还想看更细的
141
141
 
142
- - 全局 skill:`~/.qoder/skills/openxiangda/SKILL.md`(root 决策卡)+ 9 个子 skill。
142
+ - 全局 V1 skill:`~/.qoder/skills/openxiangda-v1/SKILL.md`(V1 决策卡)+ 9 个子 skill;`openxiangda` 由统一分发入口管理。
143
143
  - 资源 / 连接器 manifest:`docs/openxiangda-resources-and-connectors.md`(来自 openxiangda 仓库)。
144
144
  - 平台数据模型:`references/platform-data-model.md`(option `{label, value}`、附件、成员字段等持久化形态)。
145
145
  - 排错清单:`references/troubleshooting.md`。
@@ -4,7 +4,7 @@ export default defineAppWorkspaceConfig({
4
4
  deliveryVersion: 2,
5
5
  appType: process.env.APP_TYPE || process.env.OPENXIANGDA_APP_TYPE || "APP_XXXXXXXXXXXXXXXX",
6
6
  appName: process.env.APP_NAME || "低代码应用",
7
- platformUrl: process.env.APP_PLATFORM_URL || process.env.OPENXIANGDA_BASE_URL || "http://yida.wisejob.cn/service",
7
+ platformUrl: process.env.APP_PLATFORM_URL || process.env.OPENXIANGDA_BASE_URL || "http://platform.example.com/service",
8
8
  servicePrefix: process.env.APP_SERVICE_PREFIX || "/service",
9
9
  appKey: process.env.APP_KEY || "",
10
10
  appSecret: process.env.APP_SECRET || "",
package/v2/README.md DELETED
@@ -1,35 +0,0 @@
1
- # OpenXiangda 2.0 toolchain
2
-
3
- This directory is the isolated OpenXiangda 2.0 package workspace. It does not
4
- import or dispatch the 1.x CLI implementation in `lib/cli.js`.
5
-
6
- Current packages:
7
-
8
- - `@openxiangda/contracts`: versioned wire contracts and JSON Schemas.
9
- - `@openxiangda/compiler`: deterministic configuration, generated contracts and AppPackage sealing.
10
- - `@openxiangda/devkit-core`: framework-neutral workspace, package and control-plane use cases.
11
- - `@openxiangda/nest`: trusted Principal/RoleSession Guard, Data API client,
12
- signed CloudEvents receiver and standard backend health endpoints.
13
- - `@openxiangda/admin`: React + Ant Design application shell, capability-aware
14
- data pages and protocol-driven Workflow v2/1.x compatibility pages.
15
- - `@openxiangda/testing`: permission fixtures, allow/deny matrix assertions and
16
- local event record/replay/simulation.
17
- - `create-openxiangda`: distributable standard application workspace creator.
18
- - `@openxiangda/cli`: thin Oclif application-level CLI.
19
- - `@openxiangda/mcp`: structured AI resources and tools over the same services.
20
- - `@openxiangda/skill-kit`: validation, packaging and installation for the 2.0 domain skills.
21
-
22
- `templates/application` is the build-verified React 19 + NestJS 11 golden
23
- workspace. None of these packages imports or dispatches the 1.x CLI, so this
24
- toolchain can evolve without increasing the stable 1.x launcher surface.
25
-
26
- ```bash
27
- pnpm install
28
- pnpm check
29
- pnpm test
30
- pnpm template:build
31
- pnpm skills:check
32
- pnpm docs:build
33
- ```
34
-
35
- The fixed Changesets group publishes the packages as one compatible version train. See `docs/getting-started.md` for application usage and `docs/migration.md` for the strict 1.x coexistence boundary.
@@ -1,45 +0,0 @@
1
- {
2
- "schemaVersion": 1,
3
- "skills": [
4
- {
5
- "name": "openxiangda-v1-maintenance",
6
- "description": "Maintain an existing stable OpenXiangda 1.x application without migrating it. Use for scoped fixes to legacy pages, forms, resources, App Function code, automation, workflow, or 1.x release records.",
7
- "sha256": "7f554b8092397a0994f6aba70be38d2ec7eaf7524a075d68fb99ecbc95303525"
8
- },
9
- {
10
- "name": "openxiangda-v2",
11
- "description": "Build, inspect, validate, and deliver a complete OpenXiangda 2.0 application workspace. Use when a task spans the React frontend, NestJS backend, Data API, authorization, workflow, events, or whole-application delivery.",
12
- "sha256": "5645e5cb1c18731d5b5fb21c9ad0e59b9760600794705bb4adcad1d0e316010b"
13
- },
14
- {
15
- "name": "openxiangda-v2-architecture",
16
- "description": "Design OpenXiangda 2.0 application boundaries and typed contracts. Use when creating an app, decomposing frontend and backend responsibilities, or changing Data, AuthZ, workflow, event, or deployment declarations.",
17
- "sha256": "02768b17e048c623a13b9a99e5cedc72c9081eaa71b346c3d9db3ca66c95bf5e"
18
- },
19
- {
20
- "name": "openxiangda-v2-backend",
21
- "description": "Build the standard OpenXiangda 2.0 NestJS application backend. Use when implementing App APIs, Data API transactions, identity-aware business services, event consumers, health checks, or external integration endpoints.",
22
- "sha256": "04c3de82f4406eaeb378910fbd53e2721c13e1cb9afbeb39f1c63f352522dd39"
23
- },
24
- {
25
- "name": "openxiangda-v2-data-authz",
26
- "description": "Design OpenXiangda 2.0 Data API and contextual authorization contracts. Use for RBAC, active-role behavior, department or record attributes, application-admin bypass, field policies, and restricted transactions.",
27
- "sha256": "595fe9b8edc1e9b33720de21ed8758d4c266143c84fcb9eccc25a6adb5cce061"
28
- },
29
- {
30
- "name": "openxiangda-v2-delivery",
31
- "description": "Validate, build, deploy, observe, promote, retry, and roll back an OpenXiangda 2.0 application. Use when preparing an immutable AppPackage or changing a platform-managed environment.",
32
- "sha256": "0ee0ffef78ebe37f60319bbf5684522ce61f8d6d084c360f46dc7bb2a31d1906"
33
- },
34
- {
35
- "name": "openxiangda-v2-frontend",
36
- "description": "Build OpenXiangda 2.0 React and Ant Design admin experiences. Use when implementing menus, routes, CRUD pages, role switching, workflow task pages, or application-defined action components.",
37
- "sha256": "26add1dadeaf9a0a25d41163fb65cb70c1c5c7d882d57922193c3bd11d9d3e05"
38
- },
39
- {
40
- "name": "openxiangda-v2-workflow-events",
41
- "description": "Implement OpenXiangda Workflow Kernel v2 and durable application events. Use for approval definitions, assignee providers, task actions, delegation, add-sign, previews, data-change events, workflow events, or timers.",
42
- "sha256": "e32a5dc84e21d32a00fbfff62a349d848b04d44a569eb4f89b390901f54bb19e"
43
- }
44
- ]
45
- }
@@ -1,21 +0,0 @@
1
- ---
2
- name: openxiangda-v1-maintenance
3
- description: Maintain an existing stable OpenXiangda 1.x application without migrating it. Use for scoped fixes to legacy pages, forms, resources, App Function code, automation, workflow, or 1.x release records.
4
- ---
5
-
6
- # OpenXiangda 1.x Maintenance
7
-
8
- Preserve the installed 1.x runtime and its existing SDD, resource, function, automation, and workflow release process. Do not reinterpret the workspace as a 2.0 application package.
9
-
10
- ## Maintenance Workflow
11
-
12
- 1. Inspect the existing workspace and platform state with the installed 1.x OpenXiangda skills.
13
- 2. Run `openxiangda sdd context --json` and create or select the required SDD change.
14
- 3. Change only the named legacy resource. Keep existing identifiers and dependency order.
15
- 4. Validate 1.x JS_CODE, App Function, page, form, automation, or workflow artifacts with their dedicated 1.x skill.
16
- 5. Run `openxiangda sdd verify <change> --changed` and use the established 1.x publish gate.
17
- 6. Verify the live application without migrating its runtime, data model, or deployment topology.
18
-
19
- Do not use 2.0 build, deploy, promote, or rollback commands for a 1.x workspace. Migration is a separate, explicitly approved project.
20
-
21
- Read [1.x Migration Boundary](../../docs/migration.md) before proposing any coexistence or migration work.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 1.x Maintenance"
3
- short_description: "Maintain stable OpenXiangda 1.x applications safely"
4
- default_prompt: "Use $openxiangda-v1-maintenance to make a scoped maintenance change to this 1.x application."
@@ -1,38 +0,0 @@
1
- ---
2
- name: openxiangda-v2
3
- description: Build, inspect, validate, and deliver a complete OpenXiangda 2.0 application workspace. Use when a task spans the React frontend, NestJS backend, Data API, authorization, workflow, events, or whole-application delivery.
4
- ---
5
-
6
- # OpenXiangda 2.0
7
-
8
- Treat the repository as one typed application product. Work through package contracts and deterministic commands; do not mutate platform resources one at a time.
9
-
10
- ## Start Here
11
-
12
- 1. Run `openxiangda app info` and inspect the returned workspace and platform contract versions.
13
- 2. Read `openxiangda.config.ts`, then identify which domain skill applies:
14
- - architecture: `$openxiangda-v2-architecture`
15
- - frontend: `$openxiangda-v2-frontend`
16
- - backend: `$openxiangda-v2-backend`
17
- - data and authorization: `$openxiangda-v2-data-authz`
18
- - workflow and events: `$openxiangda-v2-workflow-events`
19
- - delivery: `$openxiangda-v2-delivery`
20
- 3. Keep generated contracts current with `openxiangda generate`.
21
- 4. Before delivery, run `openxiangda check` and `openxiangda test`.
22
-
23
- For a new repository, link it to the target platform and let an authorized platform administrator run `openxiangda app provision` once. The command is idempotent and must not be used to migrate an existing 1.x identity.
24
-
25
- ## Boundaries
26
-
27
- - Put browser code in `apps/web`, server code in `apps/server`, shared domain types in `packages/domain`, and generated declarations in `packages/contracts`.
28
- - Persist business records only through Data API or an App API implemented by the application backend.
29
- - Treat the active role and context attributes as explicit request state.
30
- - Use durable event consumers for side effects and idempotency keys for retries.
31
- - Build one immutable application package; the platform owns deployment execution, health gates, promotion, and rollback.
32
- - For a stable 1.x workspace, stop and use `$openxiangda-v1-maintenance`.
33
-
34
- ## Delivery Gate
35
-
36
- Use `openxiangda build --backend-image <immutable-image>` only after checks pass. Use `openxiangda deploy`, `openxiangda status`, and `openxiangda logs` only when the user has authorized the environment change.
37
-
38
- Read [Getting Started](../../docs/getting-started.md) for the complete development loop.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 2.0"
3
- short_description: "Build and deliver typed OpenXiangda 2.0 applications"
4
- default_prompt: "Use $openxiangda-v2 to build and validate this OpenXiangda 2.0 application."
@@ -1,29 +0,0 @@
1
- ---
2
- name: openxiangda-v2-architecture
3
- description: Design OpenXiangda 2.0 application boundaries and typed contracts. Use when creating an app, decomposing frontend and backend responsibilities, or changing Data, AuthZ, workflow, event, or deployment declarations.
4
- ---
5
-
6
- # OpenXiangda 2.0 Architecture
7
-
8
- Design one independently versioned application with a standard React frontend and NestJS backend.
9
-
10
- ## Design Sequence
11
-
12
- 1. Inspect the workspace with `openxiangda app info`.
13
- 2. Define business aggregates and invariants in `packages/domain`.
14
- 3. Declare Data API resources, capabilities, policies, workflow definitions, event subscriptions, and timers in `openxiangda.config.ts`.
15
- 4. Keep synchronous user interactions in App APIs; move retryable side effects to event consumers.
16
- 5. Use a workflow provider when assignee resolution or a workflow action depends on application data.
17
- 6. Generate types with `openxiangda generate`, then run `openxiangda check`.
18
-
19
- ## Required Decisions
20
-
21
- - Name every resource, capability, event type, workflow, and provider with a stable application-scoped code.
22
- - Separate business data from workflow runtime state.
23
- - Define the authorization context needed for each operation, including active role and data attributes.
24
- - Define idempotency and concurrency behavior before implementing writes.
25
- - Define health, readiness, and rollback expectations as part of the application contract.
26
-
27
- Do not design environment-specific code paths. Environment values and secrets are injected by the platform at deployment time.
28
-
29
- Read [Concepts](../../docs/concepts.md) before introducing a new platform-facing contract.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 2.0 Architecture"
3
- short_description: "Design typed OpenXiangda 2.0 application boundaries"
4
- default_prompt: "Use $openxiangda-v2-architecture to design this OpenXiangda 2.0 application."
@@ -1,28 +0,0 @@
1
- ---
2
- name: openxiangda-v2-backend
3
- description: Build the standard OpenXiangda 2.0 NestJS application backend. Use when implementing App APIs, Data API transactions, identity-aware business services, event consumers, health checks, or external integration endpoints.
4
- ---
5
-
6
- # OpenXiangda 2.0 Backend
7
-
8
- Build a normal NestJS service in `apps/server`. The platform deploys one container per application and injects identity, platform endpoints, environment configuration, and secrets.
9
-
10
- ## Request Path
11
-
12
- 1. Use the platform guard to verify the user token and construct typed request context.
13
- 2. Authorize the capability and contextual data policy before accessing records.
14
- 3. Keep invariants in domain services, not controllers.
15
- 4. Use Data API for persistence and its restricted transaction endpoint for atomic batches.
16
- 5. Require revision or idempotency keys for retryable writes.
17
- 6. Return stable application contracts and structured errors.
18
-
19
- ## Runtime Path
20
-
21
- - Expose liveness and readiness endpoints.
22
- - Consume platform events with signature verification and durable idempotency.
23
- - Keep outbound integrations behind adapters with timeouts and correlation IDs.
24
- - Read secrets only from injected environment references; never place them in source or application packages.
25
-
26
- Use `openxiangda dev` for local orchestration. Run `openxiangda check`, `openxiangda test`, and `openxiangda build --backend-image <immutable-image>` before deployment.
27
-
28
- Read [Backend](../../docs/backend.md) for the standard module layout.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 2.0 Backend"
3
- short_description: "Build standard NestJS application backend services"
4
- default_prompt: "Use $openxiangda-v2-backend to implement this OpenXiangda 2.0 backend."
@@ -1,28 +0,0 @@
1
- ---
2
- name: openxiangda-v2-data-authz
3
- description: Design OpenXiangda 2.0 Data API and contextual authorization contracts. Use for RBAC, active-role behavior, department or record attributes, application-admin bypass, field policies, and restricted transactions.
4
- ---
5
-
6
- # OpenXiangda 2.0 Data and AuthZ
7
-
8
- Model permissions as capability checks plus contextual data predicates. A role grants capabilities; policies decide which records and fields are available in the current role context.
9
-
10
- ## Authorization Model
11
-
12
- 1. Declare application roles and stable capability codes.
13
- 2. Treat the selected active role as part of each request. Do not silently union all user roles.
14
- 3. Resolve subject attributes such as departments and managed colleges from trusted platform or application providers.
15
- 4. Resolve resource attributes such as instrument manager and college from the target record.
16
- 5. Express allow rules as explicit subject, action, resource, and environment predicates.
17
- 6. Grant application administrators the declared application-admin bypass and audit every bypassed write.
18
-
19
- ## Data Rules
20
-
21
- - Declare resources and fields in `openxiangda.config.ts`; generate types with `openxiangda generate`.
22
- - Prefer server-enforced filters and field policies over client filtering.
23
- - Use revision checks for updates and restricted transaction batches for related writes.
24
- - Keep policy tests for multiple roles, role switching, cross-department denial, and administrator access.
25
-
26
- Run `openxiangda check` and `openxiangda test` after every policy or schema change.
27
-
28
- Read [Data and Authorization](../../docs/data-authz.md) for policy examples.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 2.0 Data and AuthZ"
3
- short_description: "Model Data API contracts and contextual authorization"
4
- default_prompt: "Use $openxiangda-v2-data-authz to design this application's data authorization."
@@ -1,30 +0,0 @@
1
- ---
2
- name: openxiangda-v2-delivery
3
- description: Validate, build, deploy, observe, promote, retry, and roll back an OpenXiangda 2.0 application. Use when preparing an immutable AppPackage or changing a platform-managed environment.
4
- ---
5
-
6
- # OpenXiangda 2.0 Delivery
7
-
8
- Deliver the whole application as one immutable version. The client submits intent; the platform owns durable execution and environment state.
9
-
10
- ## Preflight
11
-
12
- 1. Run `openxiangda doctor` and confirm client/platform contract compatibility.
13
- 2. For a first deployment only, confirm an authorized platform administrator has run `openxiangda app provision`.
14
- 3. Run `openxiangda generate --check`, `openxiangda check`, and `openxiangda test`.
15
- 4. Build and push the backend image; use an immutable digest reference.
16
- 5. Run `openxiangda build --backend-image <immutable-image>` and retain the returned package digest.
17
-
18
- ## Deployment
19
-
20
- - Inspect the plan before changing an environment.
21
- - Use `openxiangda deploy` only with explicit user authorization.
22
- - Follow the durable run with `openxiangda status` and `openxiangda logs`.
23
- - Use `openxiangda retry` only for retryable failed runs.
24
- - Use `openxiangda cancel <deploymentId>` to stop an obsolete or blocked run before submitting a replacement package.
25
- - Use `openxiangda promote` to move the exact same application version between environments.
26
- - Use `openxiangda rollback` to create a new run that activates a known historical version.
27
-
28
- Do not rebuild during promotion or rollback. Do not expose injected secrets in logs, manifests returned to clients, or package metadata.
29
-
30
- Read [Delivery](../../docs/delivery.md) for gates and failure handling.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 2.0 Delivery"
3
- short_description: "Build deploy observe promote and rollback whole apps"
4
- default_prompt: "Use $openxiangda-v2-delivery to validate and deploy this OpenXiangda 2.0 application."
@@ -1,21 +0,0 @@
1
- ---
2
- name: openxiangda-v2-frontend
3
- description: Build OpenXiangda 2.0 React and Ant Design admin experiences. Use when implementing menus, routes, CRUD pages, role switching, workflow task pages, or application-defined action components.
4
- ---
5
-
6
- # OpenXiangda 2.0 Frontend
7
-
8
- Build inside `apps/web` with `@openxiangda/admin`. Preserve the standard shell, role session, route guards, error handling, and typed clients.
9
-
10
- ## Implementation Rules
11
-
12
- 1. Register menus and routes through the application contribution API.
13
- 2. Gate navigation and actions with generated capability names; the server remains authoritative.
14
- 3. Use the active-role session supplied by the platform. Switching roles must refresh permissions and scoped data.
15
- 4. Use the standard CRUD and workflow modules first; add application components only for real domain interactions.
16
- 5. Render workflow actions and field policies from the backend protocol. Do not duplicate workflow transition rules in the browser.
17
- 6. Keep data calls in typed client modules rather than components.
18
-
19
- Run `openxiangda generate`, `openxiangda check`, and `openxiangda test` after changing contracts or pages. Use accessible Ant Design patterns and run the repository's Ant Design lint when available.
20
-
21
- Read [Frontend](../../docs/frontend.md) for route, menu, role, and workflow page examples.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 2.0 Frontend"
3
- short_description: "Build standard React and Ant Design application pages"
4
- default_prompt: "Use $openxiangda-v2-frontend to implement this OpenXiangda 2.0 frontend."
@@ -1,28 +0,0 @@
1
- ---
2
- name: openxiangda-v2-workflow-events
3
- description: Implement OpenXiangda Workflow Kernel v2 and durable application events. Use for approval definitions, assignee providers, task actions, delegation, add-sign, previews, data-change events, workflow events, or timers.
4
- ---
5
-
6
- # OpenXiangda 2.0 Workflow and Events
7
-
8
- The workflow kernel owns definitions, instances, tasks, transitions, delegation, add-sign, audit, and field policies. The application owns business records and application-specific logic.
9
-
10
- ## Workflow
11
-
12
- 1. Declare approval and conditional nodes in `openxiangda.config.ts`.
13
- 2. Use provider contracts for application-data-dependent assignee resolution and custom action decisions.
14
- 3. Keep submit preview and actual start on the same definition version and subject context.
15
- 4. Return allowed actions, field policies, presentation hints, and concurrency tokens from the backend.
16
- 5. Persist business changes through Data API or App API, then correlate them to the workflow action.
17
- 6. Test approve, reject, transfer, return, delegation, add-sign, duplicate requests, and stale revisions.
18
-
19
- ## Events
20
-
21
- - Subscribe to typed data and workflow events; implement idempotent consumers.
22
- - Use timers as durable event producers.
23
- - Verify signatures, propagate correlation IDs, and fail retryably for transient dependencies.
24
- - Never assume event ordering unless the contract explicitly provides a partition key.
25
-
26
- Use `openxiangda generate`, `openxiangda check`, and `openxiangda test` to keep providers and event payloads aligned.
27
-
28
- Read [Workflow and Events](../../docs/workflow-events.md) for protocol details.
@@ -1,4 +0,0 @@
1
- interface:
2
- display_name: "OpenXiangda 2.0 Workflow and Events"
3
- short_description: "Implement workflow providers and durable event consumers"
4
- default_prompt: "Use $openxiangda-v2-workflow-events to implement this workflow and event behavior."