@agile-team/wl-skills-kit 2.7.1 → 2.7.3
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/CHANGELOG.md +44 -0
- package/README.md +16 -1
- package/bin/wl-skills.js +1 -1
- package/files/.github/copilot-instructions.md +12 -0
- package/files/.github/guides/architecture.md +1 -1
- package/files/.github/skills/_best-practices.md +220 -0
- package/files/.github/skills/_registry.md +23 -19
- package/files/.github/skills/sync/_mcp-guardrail.md +109 -0
- package/files/.github/skills/sync/dict-sync/SKILL.md +208 -451
- package/files/.github/skills/sync/menu-sync/SKILL.md +34 -27
- package/files/.github/skills/sync/menu-sync/USAGE.md +17 -11
- package/files/.github/skills/sync/permission-sync/SKILL.md +240 -258
- package/mcp/api/client.js +83 -76
- package/mcp/server.js +21 -0
- package/mcp/tools/dictSync.js +6 -1
- package/mcp/tools/menuSync.js +11 -0
- package/package.json +5 -4
|
@@ -69,16 +69,19 @@ SYS_MENU_INFO.md 是 menu-sync Skill 的输入数据源:
|
|
|
69
69
|
|
|
70
70
|
---
|
|
71
71
|
|
|
72
|
-
## Phase 1:
|
|
72
|
+
## Phase 1:MCP 驱动创建菜单(当前方案)
|
|
73
73
|
|
|
74
|
-
>
|
|
75
|
-
|
|
74
|
+
> 本质是 **menu-sync-design.md 的方案 C(只增不删)**,由 AI 调 MCP 工具自动执行。
|
|
75
|
+
|
|
76
|
+
> 📖 **必读公共护栏**:`../_mcp-guardrail.md`
|
|
77
|
+
> 该文件定义了 MCP 调用纪律、错误分层判定、自愈闭环剧本。AI 首次执行 sync 类任务时必须先 `read_file` 加载它。
|
|
78
|
+
>
|
|
79
|
+
> 本 Skill 使用的 MCP 工具:`wls_menu_sync_from_report` / `wls_menu_query` / `wls_menu_upsert`。工具不可用或调用失败时,按 guardrail §2 剧本引导用户完善 `env.local.json` 后重试,**不得用 curl/手拼 HTTP 绕开 MCP**。
|
|
76
80
|
|
|
77
81
|
### 前置条件
|
|
78
82
|
|
|
79
|
-
1.
|
|
80
|
-
2.
|
|
81
|
-
3. 用户提供父级菜单 ID(`menuId`),可通过查询接口获取
|
|
83
|
+
1. MCP 已连接(工具列表中可见 `wls_menu_sync_from_report`)
|
|
84
|
+
2. `.github/skills/sync/env.local.json` 已填写 `token`(纯 JWT,不含 `bearer ` 前缀)、`gatewayPath`、`sysAppNo`、`menu.parentMenuId`、`menu.domainId`
|
|
82
85
|
|
|
83
86
|
### 输入
|
|
84
87
|
|
|
@@ -96,45 +99,47 @@ SYS_MENU_INFO.md 是 menu-sync Skill 的输入数据源:
|
|
|
96
99
|
| `C` | 菜单(页面) | `menuName`, `path`, `permission`, `component` |
|
|
97
100
|
| `A` | 动作按钮 | `menuName`, `path` |
|
|
98
101
|
|
|
99
|
-
###
|
|
102
|
+
### 执行流程(首选:一步到位)
|
|
100
103
|
|
|
101
|
-
|
|
104
|
+
**默认走 `wls_menu_sync_from_report`**——它内部完成「读报告 → 查菜单树 → 一级目录 upsert → 二级菜单 upsert」全流程:
|
|
102
105
|
|
|
103
106
|
```
|
|
104
|
-
工具:
|
|
105
|
-
|
|
106
|
-
|
|
107
|
+
工具:wls_menu_sync_from_report
|
|
108
|
+
入参:{ dryRun?: boolean, reportPath?: string } // 不传 reportPath 自动用最新 SYS_MENU_INFO*.md
|
|
109
|
+
第一次执行:先传 dryRun: true 预览,确认无误后再正式执行(去掉 dryRun)
|
|
107
110
|
```
|
|
108
111
|
|
|
109
|
-
|
|
112
|
+
### 手动拆分流程(仅当一步式不满足时)
|
|
110
113
|
|
|
111
|
-
#### Step
|
|
112
|
-
|
|
113
|
-
对于 `SYS_MENU_INFO` 中的一级目录,按 `menuName/path` 在父级 `parentMenuId` 下去重;不存在则创建,存在则复用 id。
|
|
114
|
+
#### Step 1: 查询当前 domain 菜单树(防重复 + 取父级信息)
|
|
114
115
|
|
|
115
|
-
|
|
116
|
+
```
|
|
117
|
+
工具:wls_menu_query (无参,自动读 env.local.json → menu.domainId)
|
|
118
|
+
返回:当前应用域完整菜单树
|
|
119
|
+
```
|
|
116
120
|
|
|
117
|
-
|
|
121
|
+
#### Step 2: 先创建一级目录(type=M),再创建二级页面菜单(type=C)
|
|
118
122
|
|
|
119
|
-
|
|
123
|
+
- 一级目录按 `menuName/path` 在父级 `parentMenuId` 下去重;不存在则创建,存在则复用 id
|
|
124
|
+
- 二级页面菜单的 `parentId` 必须是上一步对应目录的 id,**禁止**全部挂到根 `parentMenuId`
|
|
120
125
|
|
|
121
126
|
```
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
Sysappno: {sysAppNo}
|
|
126
|
-
Content-Type: application/json
|
|
127
|
+
工具:wls_menu_upsert
|
|
128
|
+
入参:{ items: [<下面的对象>...] }
|
|
129
|
+
```
|
|
127
130
|
|
|
128
|
-
|
|
131
|
+
**`items[]` 单条对象模板(仅作为 MCP 入参参考,禁止 AI 自行 fetch)**:
|
|
132
|
+
|
|
133
|
+
```jsonc
|
|
129
134
|
{
|
|
130
135
|
"useCache": 1,
|
|
131
136
|
"icon": "list",
|
|
132
137
|
"common": 2,
|
|
133
138
|
"hidden": false,
|
|
134
|
-
"type": "C",
|
|
135
|
-
"parentId": "{
|
|
139
|
+
"type": "C", // "M"=目录, "C"=菜单, "A"=动作
|
|
140
|
+
"parentId": "{父级目录的 id}",
|
|
136
141
|
"sysAppNo": "{sysAppNo}",
|
|
137
|
-
"orderNum":
|
|
142
|
+
"orderNum": 1,
|
|
138
143
|
"menuName": "客户档案",
|
|
139
144
|
"menuNameCode": "{parentMenuNameCode}:{pinyinName}",
|
|
140
145
|
"path": "mmwrCustomerArchive",
|
|
@@ -143,6 +148,8 @@ Body:
|
|
|
143
148
|
}
|
|
144
149
|
```
|
|
145
150
|
|
|
151
|
+
> **MCP 内部说明**(AI 不可据此自行调接口):底层走 `POST /system/menu/save`,成功码 `code: 2000`。
|
|
152
|
+
|
|
146
153
|
#### Step 3: 记录结果
|
|
147
154
|
|
|
148
155
|
创建完成后输出结果表格:
|
|
@@ -31,18 +31,22 @@
|
|
|
31
31
|
|
|
32
32
|
## 前置条件
|
|
33
33
|
|
|
34
|
-
`.github/skills/sync/
|
|
34
|
+
`.github/skills/sync/env.local.json`(首次使用先填写,已加入 `.gitignore`):
|
|
35
35
|
|
|
36
36
|
```json
|
|
37
37
|
{
|
|
38
|
-
"gatewayPath": "
|
|
39
|
-
"
|
|
40
|
-
"
|
|
41
|
-
"
|
|
38
|
+
"gatewayPath": "http://192.168.10.50:9000",
|
|
39
|
+
"sysAppNo": "应用编码(非明文,从已有菜单接口响应获取)",
|
|
40
|
+
"token": "eyJhbGci...(纯 JWT,不含 bearer 前缀)",
|
|
41
|
+
"menu": {
|
|
42
|
+
"parentMenuId": "父级菜单 ID(菜单管理后台获取)",
|
|
43
|
+
"domainId": "应用域 ID(Network 面板 getMenuTreeByDomainId?domainId=xxx 获取)"
|
|
44
|
+
}
|
|
42
45
|
}
|
|
43
46
|
```
|
|
44
47
|
|
|
45
|
-
> **`env.local.json` 不入 git
|
|
48
|
+
> **`env.local.json` 不入 git**。每个开发者本地填自己的 token(更新 token 时只换 token 字段,其他不动)。
|
|
49
|
+
> 字段获取详见 `env/guide.md`。
|
|
46
50
|
|
|
47
51
|
---
|
|
48
52
|
|
|
@@ -54,11 +58,11 @@ AI:[Pre-flight]
|
|
|
54
58
|
步骤 1:读取线上菜单基线 reports/SYS_MENU_INFO.md(最新更新:2025-04-20)
|
|
55
59
|
步骤 2:扫描 src/views/produce/aiflow/ 共 7 个页面
|
|
56
60
|
步骤 3:对比缺失:5 项缺失,2 项已存在
|
|
57
|
-
步骤 4:将调用
|
|
61
|
+
步骤 4:将调用 wls_menu_sync_from_report 创建 5 项
|
|
58
62
|
[需你确认]:
|
|
59
|
-
- 父菜单:精整作业 → 客户管理(
|
|
60
|
-
- 排序:
|
|
61
|
-
- 权限标识:
|
|
63
|
+
- 父菜单:精整作业 → 客户管理(menu.parentMenuId: xxx)
|
|
64
|
+
- 排序:orderNum 自动递增
|
|
65
|
+
- 权限标识:mmwrCustomerArchive 等
|
|
62
66
|
确认 yes/no?
|
|
63
67
|
```
|
|
64
68
|
|
|
@@ -78,8 +82,10 @@ AI:[Pre-flight]
|
|
|
78
82
|
| -------------------- | ---------------------------- | ---------------------------------------------- |
|
|
79
83
|
| 同步成功但 UI 看不到 | 用户角色没分配新菜单 | 跑 permission-sync(PLANNED)或后台手工分配 |
|
|
80
84
|
| 401/403 报错 | env.local.json 的 token 过期 | 重新登录系统,从 Network 抓 Authorization 替换 |
|
|
85
|
+
| AI 用 curl/Invoke-RestMethod 调接口,返回 4004 | AI 没走 MCP,自行拼接了错误的接口路径 | 确认 MCP 已连接(Cursor/Kiro 设置里可见 wls_menu_sync_from_report),然后重新说「帮我同步菜单」|
|
|
86
|
+
| token 填了 `Bearer eyJ...` 整串,接口 401 | Authorization Header 变成 `Bearer Bearer eyJ...` | token 字段只填 `eyJ...` 纯 JWT 部分,去掉 `bearer ` 前缀 |
|
|
81
87
|
| 同名菜单重复创建 | 没读 SYS_MENU_INFO.md 基线 | 先跑一遍"刷新基线"再 sync |
|
|
82
|
-
| 父菜单 ID 不对 |
|
|
88
|
+
| 父菜单 ID 不对 | menu.parentMenuId 配错 | 从菜单后台编辑页复制菜单 ID,填入 env.local.json |
|
|
83
89
|
|
|
84
90
|
---
|
|
85
91
|
|