openyida 2026.7.9 → 2026.7.10

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 (27) hide show
  1. package/package.json +1 -1
  2. package/scripts/postinstall.js +23 -23
  3. package/scripts/validate-skills.js +175 -0
  4. package/yida-skills/SKILL.md +66 -56
  5. package/yida-skills/references/development-rules.md +2 -2
  6. package/yida-skills/skills/yida-app/SKILL.md +83 -74
  7. package/yida-skills/skills/yida-canvas-custom-page/SKILL.md +1 -1
  8. package/yida-skills/skills/yida-canvas-custom-page/references/canvas-design-system.md +1 -1
  9. package/yida-skills/skills/yida-chart/SKILL.md +2 -2
  10. package/yida-skills/skills/yida-chart/references/echarts-bindding-guide.md +1 -1
  11. package/yida-skills/skills/yida-chart/references/echarts-code-template.md +1 -1
  12. package/yida-skills/skills/yida-chart/references/echarts-design-spec.md +1 -1
  13. package/yida-skills/skills/yida-create-process/SKILL.md +2 -2
  14. package/yida-skills/skills/yida-custom-page/SKILL.md +2 -2
  15. package/yida-skills/skills/yida-custom-page/references/coding-guide.md +1 -1
  16. package/yida-skills/skills/yida-custom-page/references/design-system.md +1 -1
  17. package/yida-skills/skills/yida-dashboard/SKILL.md +1 -1
  18. package/yida-skills/skills/yida-integration/SKILL.md +1 -1
  19. package/yida-skills/skills/yida-page-uiux/SKILL.md +1 -1
  20. package/yida-skills/skills/yida-page-uiux/workflow/step-0-nav-shape.md +2 -2
  21. package/yida-skills/skills/yida-ppt/SKILL.md +2 -2
  22. package/yida-skills/skills/yida-ppt-slider/SKILL.md +1 -1
  23. package/yida-skills/skills/yida-ppt-slider/references/echarts-race-example.md +1 -1
  24. package/yida-skills/skills/yida-process-rule/SKILL.md +1 -1
  25. package/yida-skills/skills/yida-publish-page/SKILL.md +2 -2
  26. package/yida-skills/skills/yida-table-form/references/examples.md +1 -1
  27. package/yida-skills/skills-index.json +430 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openyida",
3
- "version": "2026.7.9",
3
+ "version": "2026.7.10",
4
4
  "description": "OpenYida CLI - 宜搭低代码 AI 开发工具(安装即用,零配置)",
5
5
  "bin": {
6
6
  "openyida": "bin/yida.js",
@@ -251,32 +251,32 @@ openyida copy
251
251
 
252
252
  ## 子技能索引
253
253
 
254
- 根据用户意图选择最匹配的子技能,并在执行前读取对应 \`SKILL.md\`:
254
+ 根据用户意图选择最匹配的子技能。支持 \`use_skill\` / \`search_skills\` 的宿主中,必须调用 \`use_skill("<技能名>", "<本次目的>")\` 加载子技能;不要用 Read / read_file / cat 读取 SKILL.md 路径。\`skills-index.json\` 仅供 yida-agent 或同构宿主机器发现,不支持该索引的宿主忽略它。完全没有 \`use_skill\` 的本地工具,才允许按根技能路由表和技能包相对路径逐个读取当前阶段唯一必要的 SKILL.md,禁止并发批量读取多个 SKILL.md。
255
255
 
256
256
  | 意图 | 子技能 |
257
257
  | --- | --- |
258
- | 完整应用开发编排 | \`../yida-app/SKILL.md\` |
259
- | 登录态管理 | \`../yida-login/SKILL.md\` |
260
- | 退出登录 / 切换账号 | \`../yida-logout/SKILL.md\` |
261
- | 创建应用 | \`../yida-create-app/SKILL.md\` |
262
- | 创建自定义页面 | \`../yida-create-page/SKILL.md\` |
263
- | 创建 / 更新表单页面 | \`../yida-create-form-page/SKILL.md\` |
264
- | 创建流程表单 | \`../yida-create-process/SKILL.md\` |
265
- | 获取单个 / 全部表单 Schema | \`../yida-get-schema/SKILL.md\` |
266
- | 自定义页面 JSX 开发 | \`../yida-custom-page/SKILL.md\` |
267
- | 发布自定义页面 | \`../yida-publish-page/SKILL.md\` |
268
- | 页面公开访问 / 分享配置 | \`../yida-page-config/SKILL.md\` |
269
- | 表单权限 | \`../yida-form-permission/SKILL.md\` |
270
- | 数据查询与管理 | \`../yida-data-management/SKILL.md\` |
271
- | 流程规则 | \`../yida-process-rule/SKILL.md\` |
272
- | 集成自动化 | \`../yida-integration/SKILL.md\` |
273
- | HTTP 连接器 | \`../yida-connector/SKILL.md\` |
274
- | 图表页面 | \`../yida-chart/SKILL.md\` |
275
- | 原生报表 | \`../yida-report/SKILL.md\` |
276
- | 公式字段 | \`../yida-formula/SKILL.md\` |
277
- | 公式静态检查 | \`../yida-formula-evaluate/SKILL.md\` |
278
- | VOC 反馈整理 | \`../yida-voc/SKILL.md\` |
279
- | 闪记 / 会议纪要转 PRD | \`../yida-flash-note-to-prd/SKILL.md\` |
258
+ | 完整应用开发编排 | \`yida-app\` |
259
+ | 登录态管理 | \`yida-login\` |
260
+ | 退出登录 / 切换账号 | \`yida-logout\` |
261
+ | 创建应用 | \`yida-create-app\` |
262
+ | 创建自定义页面 | \`yida-create-page\` |
263
+ | 创建 / 更新表单页面 | \`yida-create-form-page\` |
264
+ | 创建流程表单 | \`yida-create-process\` |
265
+ | 获取单个 / 全部表单 Schema | \`yida-get-schema\` |
266
+ | 自定义页面 JSX 开发 | \`yida-custom-page\` |
267
+ | 发布自定义页面 | \`yida-publish-page\` |
268
+ | 页面公开访问 / 分享配置 | \`yida-page-config\` |
269
+ | 表单权限 | \`yida-form-permission\` |
270
+ | 数据查询与管理 | \`yida-data-management\` |
271
+ | 流程规则 | \`yida-process-rule\` |
272
+ | 集成自动化 | \`yida-integration\` |
273
+ | HTTP 连接器 | \`yida-connector\` |
274
+ | 图表页面 | \`yida-chart\` |
275
+ | 原生报表 | \`yida-report\` |
276
+ | 公式字段 | \`yida-formula\` |
277
+ | 公式静态检查 | \`yida-formula-evaluate\` |
278
+ | VOC 反馈整理 | \`yida-voc\` |
279
+ | 闪记 / 会议纪要转 PRD | \`yida-flash-note-to-prd\` |
280
280
 
281
281
  ## 执行规则
282
282
 
@@ -9,6 +9,7 @@ const ROOT = path.resolve(__dirname, '..');
9
9
  const SKILLS_ROOT = path.join(ROOT, 'yida-skills');
10
10
  const SKILLS_DIR = path.join(SKILLS_ROOT, 'skills');
11
11
  const INDEX_FILE = path.join(SKILLS_ROOT, 'SKILL.md');
12
+ const SKILLS_INDEX_FILE = path.join(SKILLS_ROOT, 'skills-index.json');
12
13
  const MAX_RECOMMENDED_LINES = 500;
13
14
 
14
15
  const errors = [];
@@ -22,6 +23,10 @@ function readText(filePath) {
22
23
  return fs.readFileSync(filePath, 'utf8');
23
24
  }
24
25
 
26
+ function readJson(filePath) {
27
+ return JSON.parse(readText(filePath));
28
+ }
29
+
25
30
  function collectMarkdownFiles(dir, files) {
26
31
  if (!fs.existsSync(dir)) {
27
32
  return;
@@ -159,6 +164,158 @@ function validateIndexEntry(skillDirName, skillFile) {
159
164
  }
160
165
  }
161
166
 
167
+ function validateSkillsIndex(skillDirNames) {
168
+ if (!fs.existsSync(SKILLS_INDEX_FILE)) {
169
+ errors.push(toRelative(SKILLS_INDEX_FILE) + ': missing machine-readable skills index');
170
+ return;
171
+ }
172
+
173
+ let index;
174
+ try {
175
+ index = readJson(SKILLS_INDEX_FILE);
176
+ } catch (error) {
177
+ errors.push(toRelative(SKILLS_INDEX_FILE) + ': invalid JSON: ' + error.message);
178
+ return;
179
+ }
180
+
181
+ if (index.version !== 1) {
182
+ errors.push(toRelative(SKILLS_INDEX_FILE) + ': version must be 1');
183
+ }
184
+ if (index.source !== 'openyida') {
185
+ errors.push(toRelative(SKILLS_INDEX_FILE) + ': source must be "openyida"');
186
+ }
187
+ if (index.entry !== 'openyida') {
188
+ errors.push(toRelative(SKILLS_INDEX_FILE) + ': entry must be "openyida"');
189
+ }
190
+ if (!Array.isArray(index.skills)) {
191
+ errors.push(toRelative(SKILLS_INDEX_FILE) + ': skills must be an array');
192
+ return;
193
+ }
194
+
195
+ const expectedPaths = new Set(skillDirNames.map(function(skillDirName) {
196
+ return 'skills/' + skillDirName + '/SKILL.md';
197
+ }));
198
+ const seenNames = new Set();
199
+ const seenPaths = new Set();
200
+
201
+ for (let i = 0; i < index.skills.length; i++) {
202
+ const entry = index.skills[i];
203
+ const entryLabel = toRelative(SKILLS_INDEX_FILE) + ': skills[' + i + ']';
204
+
205
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
206
+ errors.push(entryLabel + ': entry must be an object');
207
+ continue;
208
+ }
209
+
210
+ if (!entry.name || typeof entry.name !== 'string') {
211
+ errors.push(entryLabel + ': missing string field "name"');
212
+ } else if (seenNames.has(entry.name)) {
213
+ errors.push(entryLabel + ': duplicate name "' + entry.name + '"');
214
+ } else {
215
+ seenNames.add(entry.name);
216
+ }
217
+
218
+ if (!entry.path || typeof entry.path !== 'string') {
219
+ errors.push(entryLabel + ': missing string field "path"');
220
+ continue;
221
+ }
222
+ if (seenPaths.has(entry.path)) {
223
+ errors.push(entryLabel + ': duplicate path "' + entry.path + '"');
224
+ } else {
225
+ seenPaths.add(entry.path);
226
+ }
227
+
228
+ if (!/^skills\/[a-z0-9-]+\/SKILL\.md$/.test(entry.path)) {
229
+ errors.push(entryLabel + ': path must look like skills/<skill-name>/SKILL.md');
230
+ continue;
231
+ }
232
+
233
+ const skillFile = path.join(SKILLS_ROOT, entry.path);
234
+ if (!fs.existsSync(skillFile)) {
235
+ errors.push(entryLabel + ': path does not exist: ' + entry.path);
236
+ continue;
237
+ }
238
+
239
+ const content = readText(skillFile);
240
+ const frontmatter = parseFrontmatter(content);
241
+ const frontmatterName = frontmatter ? frontmatterField(frontmatter, 'name') : null;
242
+ if (frontmatterName && entry.name !== frontmatterName) {
243
+ errors.push(entryLabel + ': name "' + entry.name + '" does not match frontmatter name "' + frontmatterName + '"');
244
+ }
245
+
246
+ const pathSkillName = entry.path.split('/')[1];
247
+ if (entry.name && entry.name !== pathSkillName) {
248
+ errors.push(entryLabel + ': name "' + entry.name + '" does not match path skill name "' + pathSkillName + '"');
249
+ }
250
+
251
+ if (!entry.display_name || typeof entry.display_name !== 'string') {
252
+ errors.push(entryLabel + ': missing string field "display_name"');
253
+ }
254
+ if (!entry.description || typeof entry.description !== 'string') {
255
+ errors.push(entryLabel + ': missing string field "description"');
256
+ }
257
+ if (!entry.category || typeof entry.category !== 'string') {
258
+ errors.push(entryLabel + ': missing string field "category"');
259
+ }
260
+ if (!Array.isArray(entry.tags) || entry.tags.length === 0) {
261
+ errors.push(entryLabel + ': tags must be a non-empty array');
262
+ }
263
+ }
264
+
265
+ for (const expectedPath of expectedPaths) {
266
+ if (!seenPaths.has(expectedPath)) {
267
+ errors.push(toRelative(SKILLS_INDEX_FILE) + ': missing skill path "' + expectedPath + '"');
268
+ }
269
+ }
270
+ }
271
+
272
+ function validateSkillLoadingInstructions(instructionFiles) {
273
+ const forbiddenPatterns = [
274
+ {
275
+ pattern: /skills\/[a-z0-9-]+\/SKILL\.md/,
276
+ message: 'must load subskills via use_skill instead of source skill paths',
277
+ },
278
+ {
279
+ pattern: /\.\.\/[a-z0-9-]+\/SKILL\.md/,
280
+ message: 'must load sibling subskills via use_skill instead of relative SKILL.md paths',
281
+ },
282
+ {
283
+ pattern: /(?:先读|先读取|完整读取|完整学习|读它的|详见|参考|查阅).{0,60}SKILL\.md/,
284
+ message: 'must not instruct agents to read SKILL.md directly',
285
+ },
286
+ {
287
+ pattern: /未读取.{0,60}SKILL\.md/,
288
+ message: 'must express prerequisites as loaded skills, not direct SKILL.md reads',
289
+ },
290
+ {
291
+ pattern: /一次性(?:读取|加载).{0,40}(?:全部|多个|全量).{0,20}技能|全部技能文档/,
292
+ message: 'must not describe bulk loading multiple skills',
293
+ },
294
+ ];
295
+
296
+ for (const instructionFile of instructionFiles) {
297
+ const content = readText(instructionFile);
298
+ const lines = content.split(/\r?\n/);
299
+ for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
300
+ const line = lines[lineIndex];
301
+ const isAllowedFallback = /没有\s*`?use_skill\/search_skills`?|当前阶段唯一必要/.test(line);
302
+ const isAllowedBan = /禁止.*(?:Read|read_file|cat).*SKILL\.md/.test(line);
303
+ if (isAllowedFallback || isAllowedBan) {
304
+ continue;
305
+ }
306
+
307
+ for (const rule of forbiddenPatterns) {
308
+ if (rule.pattern.test(line)) {
309
+ errors.push(
310
+ toRelative(instructionFile) + ':' + (lineIndex + 1) + ': ' + rule.message
311
+ );
312
+ break;
313
+ }
314
+ }
315
+ }
316
+ }
317
+ }
318
+
162
319
  function isExternalLink(target) {
163
320
  return /^(https?:|mailto:|tel:|app:\/\/|plugin:\/\/|#)/i.test(target);
164
321
  }
@@ -220,6 +377,7 @@ function run() {
220
377
  return fs.statSync(fullPath).isDirectory();
221
378
  }).sort();
222
379
 
380
+ const skillDirNamesWithSkillFile = [];
223
381
  for (const skillDirName of skillDirNames) {
224
382
  const skillFile = path.join(SKILLS_DIR, skillDirName, 'SKILL.md');
225
383
  if (!fs.existsSync(skillFile)) {
@@ -227,9 +385,12 @@ function run() {
227
385
  continue;
228
386
  }
229
387
 
388
+ skillDirNamesWithSkillFile.push(skillDirName);
230
389
  validateSkillFrontmatter(skillDirName, skillFile);
231
390
  validateIndexEntry(skillDirName, skillFile);
232
391
  }
392
+
393
+ validateSkillsIndex(skillDirNamesWithSkillFile);
233
394
  }
234
395
 
235
396
  const markdownFiles = [];
@@ -238,6 +399,20 @@ function run() {
238
399
  validateMarkdownLinks(markdownFile);
239
400
  }
240
401
 
402
+ const instructionFiles = [INDEX_FILE];
403
+ if (fs.existsSync(SKILLS_DIR)) {
404
+ const skillDirNames = fs.readdirSync(SKILLS_DIR).filter(function(name) {
405
+ return fs.statSync(path.join(SKILLS_DIR, name)).isDirectory();
406
+ }).sort();
407
+ for (const skillDirName of skillDirNames) {
408
+ const skillFile = path.join(SKILLS_DIR, skillDirName, 'SKILL.md');
409
+ if (fs.existsSync(skillFile)) {
410
+ instructionFiles.push(skillFile);
411
+ }
412
+ }
413
+ }
414
+ validateSkillLoadingInstructions(instructionFiles);
415
+
241
416
  if (warnings.length > 0) {
242
417
  console.warn('Skill validation warnings:');
243
418
  for (const warning of warnings) {
@@ -12,6 +12,15 @@ description: >
12
12
 
13
13
  ---
14
14
 
15
+ ## 宿主能力适配
16
+
17
+ - 如果当前宿主提供 `use_skill` / `search_skills`:必须通过 `use_skill("<技能名>", "<本阶段目的>")` 加载主技能和子技能,禁止用 `Read` / `read_file` / `cat` 读取 `SKILL.md` 路径;`use_skill` 会稳定返回技能内容和可读取的辅助文件列表。
18
+ - `skills-index.json` 仅供 yida-agent 或同构宿主做机器可读发现;不支持该索引的宿主忽略它,不要把它当作运行前置条件。
19
+ - 如果当前宿主没有 `use_skill` / `search_skills`:按本文的技能路由表选定技能名,再按技能包相对路径逐个读取当前阶段唯一必要的 `SKILL.md`;禁止并发批量读取多个 `SKILL.md`;禁止预读未来阶段技能。
20
+ - `references/`、`scripts/`、`assets/` 等辅助文件只能在已加载对应技能后按需读取。
21
+
22
+ ---
23
+
15
24
  ## 第一步:环境与登录态检测(必做必读,先于一切操作)
16
25
 
17
26
  > ⚡ **前置门槛**:确认 openyida 已安装、Node/npm 依赖达标、登录态就绪。**未通过只读验证前,禁止创建应用/页面/表单或发布等任何真实资源操作。**
@@ -36,13 +45,14 @@ description: >
36
45
  | 用户诉求信号 | 判定 | 走哪条路线 |
37
46
  |------------|------|-----------|
38
47
  | 创建/搭建/做一个 + 应用/系统/管理系统;或明确表达从零开始 | **全量搭建** | 走 [完整开发流程](#完整开发流程全量搭建),从 Step 1 顺序执行 |
39
- | 对已有应用/表单/页面的单点操作(加字段、查改数据、配公式、建报表、改权限、发布、美化…) | **单一 / 增量任务** | 到 [技能路由](#技能路由单一--增量任务) 选定 **1 个**,只读其 SKILL.md 执行,不回退流程 |
48
+ | 对已有应用/表单/页面的单点操作(加字段、查改数据、配公式、建报表、改权限、发布、美化…) | **单一 / 增量任务** | 到 [技能路由](#技能路由单一--增量任务) 选定 **1 个**,加载对应子技能执行,不回退流程 |
40
49
 
41
50
  ---
42
51
 
43
52
  ## 完整开发流程(全量搭建)
44
53
 
45
54
  > 📌 仅当第二步判定为「全量搭建」时进入;单一/增量任务请跳「技能路由」。
55
+ > 在支持 `use_skill` 的宿主中,先加载 `yida-app` 流程编排技能;进入每个阶段前,再加载该阶段唯一需要的子技能,不要预读未来阶段技能。
46
56
 
47
57
  ```
48
58
  [Step 1] 创建应用 → openyida create-app → 获得 appType
@@ -50,9 +60,9 @@ description: >
50
60
  [Step 2] 需求分析 → 写入 prd/<项目名>.md
51
61
  ↓ (必须含 MVP 边界、角色权限、核心旅程、状态机、数据约束、验收标准)
52
62
 
53
- [Step 3] 创建自定义页面 → openyida create-page → 获得 formUuid(看板用 --mode dashboard)
63
+ [Step 3](按需)创建/更新表单 → openyida create-form → 获得 formUuid + fieldId(表单)
54
64
 
55
- [Step 4](按需)创建/更新表单 → openyida create-form → 获得 formUuid(表单)
65
+ [Step 4] 创建自定义页面 → openyida create-page → 获得 formUuid(看板用 --mode dashboard)
56
66
 
57
67
  [Step 5] 编写自定义页面代码 → 先按「自定义页面选路」定链路(**默认 Code Canvas yida-canvas-custom-page**,含开放 API 读数据页;仅强依赖原生实例数据桥的页回退 native yida-custom-page)
58
68
  ↓ (首次生成面向用户的页必做:先用 yida-page-uiux 产出「视觉方向决策块」,避免统一灰白圆角的 AI 味模板脸,再交所选链路落地)
@@ -70,18 +80,18 @@ description: >
70
80
  [Step 10] 输出访问链接,用系统浏览器打开
71
81
  ```
72
82
 
73
- > **Step 5 先定视觉方向(首次生成面向用户页必做)**:写 JSX 前先用 `yida-page-uiux` 锁定视觉方向(页面类型判定 → 意图解码 → 差异化决策 → 去 AI 味自检),产出「视觉方向决策块」,再交所选链路(默认 `yida-canvas-custom-page`,回退 `yida-custom-page`)按 `design-system.md` token 落地。跳过此步会直接套用统一灰白圆角模板,生成有 AI 味的平庸页面。详见 `skills/yida-page-uiux/SKILL.md`。
83
+ > **Step 5 先定视觉方向(首次生成面向用户页必做)**:写 JSX 前调用 `use_skill("yida-page-uiux", "确定自定义页面视觉方向并产出决策块")` 锁定视觉方向(页面类型判定 → 意图解码 → 差异化决策 → 去 AI 味自检),产出「视觉方向决策块」,再交所选链路(默认 `yida-canvas-custom-page`,回退 `yida-custom-page`)按 `design-system.md` token 落地。跳过此步会直接套用统一灰白圆角模板,生成有 AI 味的平庸页面。
74
84
  >
75
- > **Step 7 导航整理(含看板/多页面时必做)**:首次生成完整应用后,必须基于业务信息架构重排导航,不能保留创建时的默认顺序。默认原则:面向决策者的**总览/驾驶舱看板作为应用门面靠前**,数据录入/明细表单在其后;同级多个专题看板按业务优先级排,不要把所有页面无脑堆最前。详见 `skills/yida-nav-group/SKILL.md`。
85
+ > **Step 7 导航整理(含看板/多页面时必做)**:首次生成完整应用后,必须基于业务信息架构重排导航,不能保留创建时的默认顺序。默认原则:面向决策者的**总览/驾驶舱看板作为应用门面靠前**,数据录入/明细表单在其后;同级多个专题看板按业务优先级排,不要把所有页面无脑堆最前。进入本阶段前调用 `use_skill("yida-nav-group", "整理应用导航顺序")`。
76
86
  >
77
- > **Step 8 灌入示例数据(有表单时默认执行)**:新建应用的表单默认无数据,看板会空。导航整理完成后,默认向核心表单灌入 **2-3 条**覆盖关键维度(如不同活动/渠道/日期)的示例记录,让看板首屏可展示真实聚合效果。`DateField`/`CascadeDateField` 必须用 13 位毫秒时间戳;灌后执行 `openyida data query` 抽查至少 1 条,确认字段值非空。详见 `skills/yida-data-management/SKILL.md`。
87
+ > **Step 8 灌入示例数据(有表单时默认执行)**:新建应用的表单默认无数据,看板会空。导航整理完成后,默认向核心表单灌入 **2-3 条**覆盖关键维度(如不同活动/渠道/日期)的示例记录,让看板首屏可展示真实聚合效果。`DateField`/`CascadeDateField` 必须用 13 位毫秒时间戳;灌后执行 `openyida data query` 抽查至少 1 条,确认字段值非空。进入本阶段前调用 `use_skill("yida-data-management", "写入和抽查示例数据")`。
78
88
 
79
89
  ---
80
90
 
81
91
  ## 技能路由(单一 / 增量任务)
82
92
 
83
93
  > 选定 **1 个**最匹配的项执行。表**按业务域分组**,每组内既可能是 skill 也可能是 CLI:
84
- > - 行名为 `yida-xxx` / `sls-log-workbench` / `large-file-write` 的是 **skill** → 先读对应子技能文档再执行;
94
+ > - 行名为 `yida-xxx` / `sls-log-workbench` / `large-file-write` 的是 **skill** → 在支持 `use_skill` 的宿主中调用 `use_skill("<技能名>", "<本次目的>")` 加载后执行;
85
95
  > - 行名为 `openyida xxx` 并标 **`CLI`** 的**无 SKILL.md** → 识别到诉求直接执行命令、**不要当 skill 去 read**。
86
96
  >
87
97
  > 按分组 +「何时选择」内联区别对号入座即可。
@@ -95,56 +105,56 @@ description: >
95
105
  >
96
106
  > 依据(源码核实):Canvas 代码在宿主页真实 `window` 中 `new Function` 执行,但物料只透传 `code/runtimeCode/importedModules/pageType`,**无 `this` 上下文、无 `dataSourceMap`**,`this.utils.yida.*` 不可用;宿主 window 全局(`__yida_plugin_runtime__` 插件系统、`__VcDeepYidaUtils__`)均非表单数据桥,也无 `window.Deep` 字段组件。Canvas 读宜搭数据 = 在 `YidaComp` 内自写 HTTP 调开放 API。只有需要免费 `this` 实例桥的页才留 native。
97
107
 
98
- | 分组 | 技能 | 何时选择(关键区别已内联) |
108
+ | 分组 | 加载目标 | 何时选择(关键区别已内联) |
99
109
  |------|------|--------------------------|
100
- | **应用与登录** | `yida-app` | 从零搭建整个应用(多步骤全流程编排) |
101
- | | `yida-create-app` | 只需创建应用、拿 appType |
102
- | | `yida-login` | 手动触发登录(通常自动触发) |
103
- | | `yida-logout` | 切换账号或组织 |
104
- | **页面与表单** | `yida-create-page` | 创建空白自定义页面拿 formUuid,后续写 JSX |
105
- | | `yida-create-form-page` | 创建/更新表单、增删改**字段结构**(普通表单,无审批) |
106
- | | `yida-create-process` | 从零建**带审批**流程表单(表单还不存在,一步到位) |
107
- | | `yida-page-uiux` | 写自定义页面 UI 前先定视觉方向、去 AI 味(工作台/看板/列表/详情/官网落地页;产出决策块,不写代码;canvas / native 两链路通用) |
108
- | | `yida-canvas-custom-page` | **自定义页面默认链路**:现代 React 交互 / hooks / 可视化 / AI 页,含只需开放 API HTTP 读数据的页(Code Canvas,`runtimeCode` + `importedModules`,真 React18 + 崩溃隔离) |
109
- | | `yida-custom-page` | 回退项:仅当强依赖原生实例数据桥(`this.$(fieldId)` 双向绑定 / `this.utils.yida.*` / `dataSourceMap` / 提交流程深度耦合)时才用(native `.oyd.jsx` 链路) |
110
- | | `yida-canvas-upgrade` | 将已有普通 `.oyd.jsx` / `Jsx` 页面升级迁移到 Code Canvas / `YidaCodeCanvas` 链路 |
111
- | | `yida-nav-shell` | 自定义页**隐藏应用导航**(`isRenderNav=false`,沉浸/门户/大屏/分享)后,页面内用 JSX 自绘侧边/顶部/浮动/标签导航壳;发布后要配置隐藏原导航,跨页导航项要拼完整 URL 并合并 `isRenderNav=false` / `corpid` / 业务参数(**区别** `yida-nav-group` 平台左侧菜单分组:那是真实导航树,本项是页面内自建导航) |
112
- | | `yida-publish-page` | JSX 写完后编译并发布 |
113
- | | `yida-openyida-publish-guard` | 发布已有自定义页面前检查线上设计器状态,避免本地旧源码覆盖用户在线改动 |
114
- | | `yida-table-form` | Excel 式表格批量录入提交 |
115
- | | `yida-ppt-slider` | 全屏幻灯片页面(分享/路演/培训/演示) |
110
+ | **应用与登录** | 加载子技能 `yida-app` | 从零搭建整个应用(多步骤全流程编排) |
111
+ | | 加载子技能 `yida-create-app` | 只需创建应用、拿 appType |
112
+ | | 加载子技能 `yida-login` | 手动触发登录(通常自动触发) |
113
+ | | 加载子技能 `yida-logout` | 切换账号或组织 |
114
+ | **页面与表单** | 加载子技能 `yida-create-page` | 创建空白自定义页面拿 formUuid,后续写 JSX |
115
+ | | 加载子技能 `yida-create-form-page` | 创建/更新表单、增删改**字段结构**(普通表单,无审批) |
116
+ | | 加载子技能 `yida-create-process` | 从零建**带审批**流程表单(表单还不存在,一步到位) |
117
+ | | 加载子技能 `yida-page-uiux` | 写自定义页面 UI 前先定视觉方向、去 AI 味(工作台/看板/列表/详情/官网落地页;产出决策块,不写代码;canvas / native 两链路通用) |
118
+ | | 加载子技能 `yida-canvas-custom-page` | **自定义页面默认链路**:现代 React 交互 / hooks / 可视化 / AI 页,含只需开放 API HTTP 读数据的页(Code Canvas,`runtimeCode` + `importedModules`,真 React18 + 崩溃隔离) |
119
+ | | 加载子技能 `yida-custom-page` | 回退项:仅当强依赖原生实例数据桥(`this.$(fieldId)` 双向绑定 / `this.utils.yida.*` / `dataSourceMap` / 提交流程深度耦合)时才用(native `.oyd.jsx` 链路) |
120
+ | | 加载子技能 `yida-canvas-upgrade` | 将已有普通 `.oyd.jsx` / `Jsx` 页面升级迁移到 Code Canvas / `YidaCodeCanvas` 链路 |
121
+ | | 加载子技能 `yida-nav-shell` | 自定义页**隐藏应用导航**(`isRenderNav=false`,沉浸/门户/大屏/分享)后,页面内用 JSX 自绘侧边/顶部/浮动/标签导航壳;发布后要配置隐藏原导航,跨页导航项要拼完整 URL 并合并 `isRenderNav=false` / `corpid` / 业务参数(**区别** `yida-nav-group` 平台左侧菜单分组:那是真实导航树,本项是页面内自建导航) |
122
+ | | 加载子技能 `yida-publish-page` | JSX 写完后编译并发布 |
123
+ | | 加载子技能 `yida-openyida-publish-guard` | 发布已有自定义页面前检查线上设计器状态,避免本地旧源码覆盖用户在线改动 |
124
+ | | 加载子技能 `yida-table-form` | Excel 式表格批量录入提交 |
125
+ | | 加载子技能 `yida-ppt-slider` | 全屏幻灯片页面(分享/路演/培训/演示) |
116
126
  | | `openyida aggregate-table` `CLI` | 聚合表 / 虚拟视图(virtualView):`list` 列出 · `create-empty` 建空白(返回设计器 URL)· `preview` 预览不保存 · `publish` 发布配置 |
117
- | **数据可视化** | `yida-report` | 普通报表/统计,开箱即用(原生 16 组件) |
118
- | | `yida-chart` | 更美观/定制化/数据大屏(ECharts) |
119
- | | `yida-dashboard` | 完整看板 / 驾驶舱产品化交付 |
120
- | **连接器** | `yida-connector` | 创建/管理连接器、配鉴权 |
121
- | | `yida-connector-safe-actions` | 连接器已有,从 API 代码生成执行动作 |
122
- | | `yida-data-source-connectors` | 自定义页面中通过数据源调用连接器 |
123
- | **数据与公式** | `yida-data-management` | 增删改查**数据记录**,不动字段结构 |
124
- | | `yida-get-schema` | **只读**查 Schema / 字段 ID,不改结构 |
125
- | | `yida-formula` | 配在**字段属性**上的实时计算/默认值/校验 |
126
- | | `yida-formula-evaluate` | 公式语法与字段引用静态检查 |
127
- | | `yida-business-rule` | 提交后**跨表**高级函数 INSERT/UPDATE/DELETE |
128
- | **流程与自动化** | `yida-process-rule` | **改已有**流程节点/分支/字段权限(表单已存在) |
129
- | | `yida-integration` | 提交后**逻辑编排**(图形化自动化流,推荐) |
130
- | | `yida-agent-center` | 流程代理(在职/离职代理人) |
127
+ | **数据可视化** | 加载子技能 `yida-report` | 普通报表/统计,开箱即用(原生 16 组件) |
128
+ | | 加载子技能 `yida-chart` | 更美观/定制化/数据大屏(ECharts) |
129
+ | | 加载子技能 `yida-dashboard` | 完整看板 / 驾驶舱产品化交付 |
130
+ | **连接器** | 加载子技能 `yida-connector` | 创建/管理连接器、配鉴权 |
131
+ | | 加载子技能 `yida-connector-safe-actions` | 连接器已有,从 API 代码生成执行动作 |
132
+ | | 加载子技能 `yida-data-source-connectors` | 自定义页面中通过数据源调用连接器 |
133
+ | **数据与公式** | 加载子技能 `yida-data-management` | 增删改查**数据记录**,不动字段结构 |
134
+ | | 加载子技能 `yida-get-schema` | **只读**查 Schema / 字段 ID,不改结构 |
135
+ | | 加载子技能 `yida-formula` | 配在**字段属性**上的实时计算/默认值/校验 |
136
+ | | 加载子技能 `yida-formula-evaluate` | 公式语法与字段引用静态检查 |
137
+ | | 加载子技能 `yida-business-rule` | 提交后**跨表**高级函数 INSERT/UPDATE/DELETE |
138
+ | **流程与自动化** | 加载子技能 `yida-process-rule` | **改已有**流程节点/分支/字段权限(表单已存在) |
139
+ | | 加载子技能 `yida-integration` | 提交后**逻辑编排**(图形化自动化流,推荐) |
140
+ | | 加载子技能 `yida-agent-center` | 流程代理(在职/离职代理人) |
131
141
  | | `openyida ai-form-setting` `CLI` | 流程表单 AI 审批提示:`models` 查模型 · `fields` 查可插入字段(TEXT/IMAGE/ATTACHMENT)· `get` 查配置 |
132
- | **权限与访问** | `yida-corp-manager` | **组织级**权限(平台/子管理员、通讯录,影响整个组织) |
133
- | | `yida-app-permission` | **单应用级**权限(应用管理员/开发成员) |
134
- | | `yida-form-permission` | **单表单级**权限(权限组/数据范围) |
135
- | | `yida-page-config` | **页面级**:公开访问 / 组织内分享 |
136
- | **应用配置与平台** | `yida-nav-group` | 应用**左侧菜单**分组/排序(真实导航树;页面内自绘导航壳见 `yida-nav-shell`) |
137
- | | `yida-form-detail` | 只注 **CSS** 美化详情页,不改字段 |
138
- | | `yida-density` | 列表/表格信息密度选择 |
139
- | | `yida-i18n` | 应用多语言 / 国际化 |
140
- | | `yida-basic-info` | 组织版本/容量/域名/额度查询 |
141
- | | `yida-corp-efficiency` | 企业效能 / 低代码学习成果 |
142
- | **辅助工具** | `yida-flash-note-to-prd` | 会议纪要/闪记转 PRD |
143
- | | `yida-export-conversation` | 导出当前对话为 Markdown |
144
- | | `yida-voc` | 整理故障/需求反馈材料 |
145
- | | `sls-log-workbench` | SLS 平台问题日志查询 |
146
- | | `yida-db-seq-fix` | PostgreSQL 主键冲突 / Sequence 修复 |
147
- | | `large-file-write` | 可靠写入 100+ 行大文件 |
142
+ | **权限与访问** | 加载子技能 `yida-corp-manager` | **组织级**权限(平台/子管理员、通讯录,影响整个组织) |
143
+ | | 加载子技能 `yida-app-permission` | **单应用级**权限(应用管理员/开发成员) |
144
+ | | 加载子技能 `yida-form-permission` | **单表单级**权限(权限组/数据范围) |
145
+ | | 加载子技能 `yida-page-config` | **页面级**:公开访问 / 组织内分享 |
146
+ | **应用配置与平台** | 加载子技能 `yida-nav-group` | 应用**左侧菜单**分组/排序(真实导航树;页面内自绘导航壳见 `yida-nav-shell`) |
147
+ | | 加载子技能 `yida-form-detail` | 只注 **CSS** 美化详情页,不改字段 |
148
+ | | 加载子技能 `yida-density` | 列表/表格信息密度选择 |
149
+ | | 加载子技能 `yida-i18n` | 应用多语言 / 国际化 |
150
+ | | 加载子技能 `yida-basic-info` | 组织版本/容量/域名/额度查询 |
151
+ | | 加载子技能 `yida-corp-efficiency` | 企业效能 / 低代码学习成果 |
152
+ | **辅助工具** | 加载子技能 `yida-flash-note-to-prd` | 会议纪要/闪记转 PRD |
153
+ | | 加载子技能 `yida-export-conversation` | 导出当前对话为 Markdown |
154
+ | | 加载子技能 `yida-voc` | 整理故障/需求反馈材料 |
155
+ | | 加载子技能 `sls-log-workbench` | SLS 平台问题日志查询 |
156
+ | | 加载子技能 `yida-db-seq-fix` | PostgreSQL 主键冲突 / Sequence 修复 |
157
+ | | 加载子技能 `large-file-write` | 可靠写入 100+ 行大文件 |
148
158
  | | `openyida ai` `CLI` | 调用宜搭 AI 通用能力:文生文(文本生成)/ 识图(图片识别) |
149
159
  | | `openyida batch` `CLI` | 批量顺序执行多条 OpenYida 命令(读 tasks 文件,支持 `--json --quiet`) |
150
160
 
@@ -154,14 +164,14 @@ description: >
154
164
 
155
165
  ### 致命规则(FATAL,违反即失败/报错)
156
166
 
157
- 1. **先读后执行**:执行任何子技能前,必须先读取其 SKILL.md,不凭记忆猜参数格式。
167
+ 1. **技能加载唯一入口**:执行任何子技能前,支持 `use_skill` 的宿主必须调用 `use_skill("<技能名>", "<本阶段目的>")` 加载对应技能;不要用 `Read` / `read_file` / `cat` 读取 SKILL.md 路径,不凭记忆猜参数格式。
158
168
  2. **corpId 一致性检查**:创建页面前对比 prd 与 `.cache/cookies.json` 的 corpId,不一致必须询问用户(重新登录 or 当前组织新建)。
159
169
  3. **发布前本地校验**:自定义页面发布前跑 `openyida check-page` + `openyida compile`;JSON 配置写盘后先解析校验,再调用平台命令。
160
170
  4. **命令输入文件禁止 shell 写入**:当 OpenYida 命令需要 JSON/YAML/CSV/config/script 文件参数时,先使用当前 agent 运行时提供的结构化文件写入工具(如 create_file / Write / file edit tool)创建文件,再把路径传给命令;禁止用 shell heredoc、`cat`/`echo`/`printf`/`tee` 加输出重定向,或把命令 stdout 重定向成业务文件。
161
171
 
162
172
  ### 重要规则(IMPORTANT,影响质量/性能/可维护性)
163
173
 
164
- 1. **只读必要文档**:按意图选 1 个主技能,禁止一次性读取全部技能文档。
174
+ 1. **按阶段加载必要技能**:按意图选 1 个主技能;完整应用按阶段加载当下唯一需要的子技能,禁止并发批量读取多个 `SKILL.md` 或预读未来阶段技能。
165
175
  2. **优先复用缓存**:`appType`/`formUuid`/`fieldId` 优先从 `.cache/<项目名>-schema.json` 读,缺失再 `get-schema`。
166
176
  3. **模板优先**:复杂产物先用 `openyida sample` 或现有示例生成骨架,再做最小改动。
167
177
  4. **配置承载优先于代码**:字段/公式/联动/报表/审批/集成交给对应技能,自定义页面只做展示与胶水。
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## 致命规则(FATAL)
6
6
 
7
- **F1 先读后执行**:执行任何子技能前,必须先读取对应子技能文档`skills/<技能名>/SKILL.md`,按文档里的参数格式操作,不凭记忆猜。
7
+ **F1 技能加载唯一入口**:执行任何子技能前,支持 `use_skill` 的宿主必须调用 `use_skill("<技能名>", "<本阶段目的>")` 加载对应技能;不要用 `Read` / `read_file` / `cat` 读取 `SKILL.md` 路径。`skills-index.json` 仅供 yida-agent 或同构宿主机器发现,不支持该索引的宿主忽略它。完全没有 `use_skill` / `search_skills` 的本地工具,才允许按根技能路由表和技能包相对路径逐个读取当前阶段唯一必要的技能文档;禁止并发批量读取多个 `SKILL.md`,禁止预读未来阶段技能。
8
8
 
9
9
  **F2 corpId 一致性检查**:创建页面前对比 prd 文档与 `.cache/cookies.json` 的 corpId——
10
10
  - 一致 → 继续;
@@ -21,7 +21,7 @@
21
21
 
22
22
  | # | 规则 | 操作细节 |
23
23
  |---|------|---------|
24
- | 1 | 只读必要文档 | 按意图选定 1 个主技能,仅在该技能明确要求时才读对应 `references/`;禁止一次性读全部技能文档。 |
24
+ | 1 | 按阶段加载必要技能 | 按意图选定 1 个主技能;完整应用按阶段加载当下唯一需要的子技能,仅在已加载技能明确要求时才读对应 `references/`。 |
25
25
  | 2 | 优先复用缓存 | `appType`/`formUuid`/`fieldId`/`reportId` 先从 `.cache/<项目名>-schema.json` 读,缺失或不确定再 `openyida get-schema`。 |
26
26
  | 3 | 模板优先 | 自定义页面、表单字段、报表配置等复杂产物先用 `openyida sample` 或现有示例生成骨架,再做最小改动。 |
27
27
  | 4 | 配置承载优先于代码 | 字段结构/公式/联动/报表聚合/审批/集成/连接器动作交给对应技能承载;自定义页面代码只做展示、事件分发和必要胶水。 |