@pm_zhousl/xinyun-ai-init 1.1.2 → 1.1.4
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/init/xinyun-ai-init/README.md +44 -0
- package/init/xinyun-ai-init/templates/core-rules.template.md +15 -0
- package/init/xinyun-ai-init/templates/current-task.template.md +2 -0
- package/init/xinyun-ai-init/templates/manifest.template.json +2 -2
- package/init/xinyun-ai-init/version.json +2 -2
- package/package.json +2 -1
- package/scripts/verify-init-package.js +203 -0
|
@@ -92,10 +92,27 @@ CLI 只负责生成 `xinyun-ai-init/`,不创建 `xinyun-ai/`,也不修改业
|
|
|
92
92
|
|
|
93
93
|
UI 类需求至少判断前端改动模式:样式微调 / 新页面 / 页面重写 / 组件重构 / 不涉及。
|
|
94
94
|
|
|
95
|
+
如果当前 AI 工具有需求分析、原型、UI 交互、截图风格识别等 Skill,仅在任务明确匹配时调用对应 Skill;不得因为普通开发任务默认启用所有 Skill。
|
|
96
|
+
|
|
95
97
|
样式微调应优先局部修改,不重写页面结构;新页面或页面重写必须先说明页面结构方案,且不得顺手修改无关页面。
|
|
96
98
|
|
|
97
99
|
普通聊天、临时咨询、无长期价值排查不沉淀。
|
|
98
100
|
|
|
101
|
+
## 商业逻辑与变现流程理解
|
|
102
|
+
|
|
103
|
+
当需求涉及金额、订单、权益、结算、优惠、积分、分润、提现、会员等级、支付状态或退款等商业逻辑时,AI 必须先做触发式业务理解。
|
|
104
|
+
|
|
105
|
+
触发后先梳理:
|
|
106
|
+
|
|
107
|
+
- 业务目标
|
|
108
|
+
- 关键角色
|
|
109
|
+
- 资金 / 权益 / 状态流转
|
|
110
|
+
- 数据库、API、UI 和测试数据影响
|
|
111
|
+
- 风险点
|
|
112
|
+
- 验收标准
|
|
113
|
+
|
|
114
|
+
该规则只在相关需求触发时启用,不默认创建 `xinyun-ai/business/`,也不在首次初始化阶段生成大量商业分析文档。
|
|
115
|
+
|
|
99
116
|
## 统一入口与旧规则失效
|
|
100
117
|
|
|
101
118
|
当前项目 AI 规则以 `xinyun-ai/` 为准,`AGENTS.md` 只作为入口文件,指向 `xinyun-ai/`。
|
|
@@ -217,9 +234,36 @@ xinyun-ai/index/project-index.json
|
|
|
217
234
|
- 问题排查:`xinyun-ai/problems/`
|
|
218
235
|
- 需求:`xinyun-ai/requirements/`
|
|
219
236
|
- 技术经验:`xinyun-ai/rules-candidates/`
|
|
237
|
+
- 全局影响审视:`xinyun-ai/global-review/`
|
|
220
238
|
|
|
221
239
|
新目录创建后必须更新 `xinyun-ai/manifest.json` 和 `xinyun-ai/index/project-index.json`。
|
|
222
240
|
|
|
241
|
+
## 通用项目全局视角
|
|
242
|
+
|
|
243
|
+
新增功能、大改、重构、跨端改动、目录 / 规则 / 索引调整时,AI 必须先做全局影响审视。
|
|
244
|
+
|
|
245
|
+
小改可以只在改动计划中简写全局影响;新功能、大改、重构、跨端改动、目录 / 规则 / 索引调整,应按需创建或更新:
|
|
246
|
+
|
|
247
|
+
```md
|
|
248
|
+
xinyun-ai/global-review/
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
全局审视不代替改动计划,它是改动计划前的影响检查。
|
|
252
|
+
|
|
253
|
+
建议审视层:
|
|
254
|
+
|
|
255
|
+
- 入口层
|
|
256
|
+
- 目录层
|
|
257
|
+
- 索引层
|
|
258
|
+
- 任务层
|
|
259
|
+
- 规则层
|
|
260
|
+
- 多端层
|
|
261
|
+
- 数据层
|
|
262
|
+
- API 层
|
|
263
|
+
- UI 层
|
|
264
|
+
- 验证层
|
|
265
|
+
- 交接层
|
|
266
|
+
|
|
223
267
|
## 会话工作台
|
|
224
268
|
|
|
225
269
|
首次初始化不创建会话工作台。复杂任务中可按需创建:
|
|
@@ -68,10 +68,17 @@
|
|
|
68
68
|
- 涉及功能、业务流程、API、数据库、页面、组件、交互或样式时,出计划前先做轻量需求理解。
|
|
69
69
|
- 信息不足时,最多问 1-3 个关键问题。
|
|
70
70
|
- UI 类需求至少判断前端改动模式:样式微调 / 新页面 / 页面重写 / 组件重构 / 不涉及。
|
|
71
|
+
- 如果当前 AI 工具有需求分析、原型、UI 交互、截图风格识别等 Skill,仅在任务明确匹配时调用对应 Skill;不得因为普通开发任务默认启用所有 Skill。
|
|
71
72
|
- 样式微调应优先局部修改,不重写页面结构。
|
|
72
73
|
- 新页面或页面重写必须先说明页面结构方案,且不得顺手修改无关页面。
|
|
73
74
|
- 普通聊天、临时咨询、无长期价值排查不沉淀。
|
|
74
75
|
|
|
76
|
+
## 商业逻辑与变现流程理解
|
|
77
|
+
|
|
78
|
+
- 当需求涉及金额、订单、权益、结算、优惠、积分、分润、提现、会员等级、支付状态或退款等商业逻辑时,先做触发式业务理解。
|
|
79
|
+
- 触发后先梳理业务目标、关键角色、资金 / 权益 / 状态流转、数据库 / API / UI / 测试数据影响、风险点和验收标准。
|
|
80
|
+
- 该规则只在相关需求触发时启用,不默认创建 `xinyun-ai/business/`。
|
|
81
|
+
|
|
75
82
|
## 检索与回复
|
|
76
83
|
|
|
77
84
|
- 先读 `AGENTS.md`、`xinyun-ai/manifest.json`、`xinyun-ai/index/project-index.json`、`xinyun-ai/current-task.md`。
|
|
@@ -104,6 +111,14 @@
|
|
|
104
111
|
|
|
105
112
|
复杂任务可按需创建 `xinyun-ai/index/session-current.md`。该文件只记录本轮临时线索,不是项目事实源。
|
|
106
113
|
|
|
114
|
+
## 通用项目全局视角
|
|
115
|
+
|
|
116
|
+
- 新增功能、大改、重构、跨端改动、目录 / 规则 / 索引调整时,先做全局影响审视。
|
|
117
|
+
- 小改可以只在改动计划中简写全局影响。
|
|
118
|
+
- 需要落盘时按需创建或更新 `xinyun-ai/global-review/`。
|
|
119
|
+
- 全局审视不代替改动计划,它是改动计划前的影响检查。
|
|
120
|
+
- 建议审视入口层、目录层、索引层、任务层、规则层、多端层、数据层、API 层、UI 层、验证层和交接层。
|
|
121
|
+
|
|
107
122
|
## 自我学习
|
|
108
123
|
|
|
109
124
|
发现可复用经验时,先记录为候选经验。候选经验必须标注来源、适用范围、可信度、状态和最后验证时间。用户确认后,才能合并进正式规则。
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"packageName": "xinyun-ai-init",
|
|
3
3
|
"displayName": "欣芸技术开发 Agent 流初始化包",
|
|
4
|
-
"version": "1.1.
|
|
5
|
-
"scriptVersion": "2026.07.
|
|
4
|
+
"version": "1.1.4",
|
|
5
|
+
"scriptVersion": "2026.07.15",
|
|
6
6
|
"schemaVersion": "1",
|
|
7
7
|
"defaultMode": "fast-init",
|
|
8
8
|
"targetWorkspace": "xinyun-ai",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pm_zhousl/xinyun-ai-init",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.4",
|
|
4
4
|
"description": "欣芸技术开发 Agent 流初始化包",
|
|
5
5
|
"bin": {
|
|
6
6
|
"xinyun-ai-init": "bin/xinyun-ai-init.js"
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
"README.md"
|
|
13
13
|
],
|
|
14
14
|
"scripts": {
|
|
15
|
+
"verify:init": "node ./scripts/verify-init-package.js",
|
|
15
16
|
"publish:token": "powershell -ExecutionPolicy Bypass -File ./scripts/publish-with-token.ps1",
|
|
16
17
|
"publish:token:dry": "powershell -ExecutionPolicy Bypass -File ./scripts/publish-with-token.ps1 -DryRun"
|
|
17
18
|
},
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
const root = path.resolve(__dirname, "..");
|
|
7
|
+
const initRoot = path.join(root, "init", "xinyun-ai-init");
|
|
8
|
+
|
|
9
|
+
const checks = [];
|
|
10
|
+
|
|
11
|
+
function rel(filePath) {
|
|
12
|
+
return path.relative(root, filePath).replace(/\\/g, "/");
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function readText(relativePath) {
|
|
16
|
+
const filePath = path.join(root, relativePath);
|
|
17
|
+
return fs.readFileSync(filePath, "utf8");
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function addCheck(name, ok, detail) {
|
|
21
|
+
checks.push({ name, ok, detail });
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function requireFile(relativePath) {
|
|
25
|
+
const filePath = path.join(root, relativePath);
|
|
26
|
+
addCheck(`文件存在:${relativePath}`, fs.existsSync(filePath), "缺少必需文件");
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function requireIncludes(relativePath, snippets) {
|
|
30
|
+
const content = readText(relativePath);
|
|
31
|
+
for (const snippet of snippets) {
|
|
32
|
+
addCheck(
|
|
33
|
+
`${relativePath} 包含:${snippet}`,
|
|
34
|
+
content.includes(snippet),
|
|
35
|
+
`未找到关键文本:${snippet}`
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function requireJson(relativePath) {
|
|
41
|
+
try {
|
|
42
|
+
JSON.parse(readText(relativePath));
|
|
43
|
+
addCheck(`JSON 可解析:${relativePath}`, true);
|
|
44
|
+
} catch (error) {
|
|
45
|
+
addCheck(`JSON 可解析:${relativePath}`, false, error.message);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function requireMarkdownBalanced(relativePath) {
|
|
50
|
+
const content = readText(relativePath);
|
|
51
|
+
const fenceCount = (content.match(/```/g) || []).length;
|
|
52
|
+
addCheck(
|
|
53
|
+
`Markdown 代码块闭合:${relativePath}`,
|
|
54
|
+
fenceCount % 2 === 0,
|
|
55
|
+
`代码块围栏数量为 ${fenceCount}`
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function walkFiles(dirPath) {
|
|
60
|
+
const result = [];
|
|
61
|
+
for (const entry of fs.readdirSync(dirPath, { withFileTypes: true })) {
|
|
62
|
+
const entryPath = path.join(dirPath, entry.name);
|
|
63
|
+
if (entry.isDirectory()) {
|
|
64
|
+
result.push(...walkFiles(entryPath));
|
|
65
|
+
} else {
|
|
66
|
+
result.push(entryPath);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return result;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function verifyPackageFiles() {
|
|
73
|
+
const packageJson = JSON.parse(readText("package.json"));
|
|
74
|
+
const expectedFiles = ["bin/", "init/", "scripts/", "README.md"];
|
|
75
|
+
|
|
76
|
+
for (const expected of expectedFiles) {
|
|
77
|
+
addCheck(
|
|
78
|
+
`package.json files 包含:${expected}`,
|
|
79
|
+
Array.isArray(packageJson.files) && packageJson.files.includes(expected),
|
|
80
|
+
"发布文件白名单缺少该路径"
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
addCheck(
|
|
85
|
+
"package.json scripts 包含 verify:init",
|
|
86
|
+
packageJson.scripts && packageJson.scripts["verify:init"] === "node ./scripts/verify-init-package.js",
|
|
87
|
+
"缺少发布前校验命令"
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function verifyCliBoundary() {
|
|
92
|
+
const cli = readText("bin/xinyun-ai-init.js");
|
|
93
|
+
|
|
94
|
+
requireIncludes("bin/xinyun-ai-init.js", [
|
|
95
|
+
"This CLI only creates xinyun-ai-init/",
|
|
96
|
+
"It does not create xinyun-ai/ or modify business code",
|
|
97
|
+
"printNextStep",
|
|
98
|
+
]);
|
|
99
|
+
|
|
100
|
+
addCheck(
|
|
101
|
+
"CLI 目标目录仅为 xinyun-ai-init",
|
|
102
|
+
cli.includes('const target = path.join(cwd, "xinyun-ai-init");'),
|
|
103
|
+
"CLI 不应直接创建 xinyun-ai/"
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function verifyInitRules() {
|
|
108
|
+
requireIncludes("init/xinyun-ai-init/README.md", [
|
|
109
|
+
"用户发送一句话入口后,AI 可以按本 README 和 `templates/` 创建或补齐首次最小落盘清单。",
|
|
110
|
+
"该授权只覆盖 AI 工作区初始化,不代表授权修改业务代码",
|
|
111
|
+
"标准改动计划",
|
|
112
|
+
"前端改动模式:样式微调 / 新页面 / 页面重写 / 组件重构 / 不涉及",
|
|
113
|
+
"当前项目 AI 规则以 `xinyun-ai/` 为准",
|
|
114
|
+
"旧 AI 文档、旧 docs、旧提示词、旧规则文件只作为历史线索,不作为执行依据",
|
|
115
|
+
"ThinkPHP、uni-app、微信小程序",
|
|
116
|
+
"涉及 SQL / 数据库改动时,必须单独输出 SQL 执行提醒",
|
|
117
|
+
"商业逻辑",
|
|
118
|
+
"xinyun-ai/global-review/",
|
|
119
|
+
]);
|
|
120
|
+
|
|
121
|
+
requireIncludes("init/xinyun-ai-init/templates/AGENTS.template.md", [
|
|
122
|
+
"当前项目 AI 规则以 `xinyun-ai/` 为准",
|
|
123
|
+
"任何代码、配置、数据库、依赖、构建脚本、测试逻辑、API 行为、UI 行为或业务流程修改前",
|
|
124
|
+
"只有用户明确回复“确认执行”“可以修改”“按方案改”“同意”等类似内容后",
|
|
125
|
+
]);
|
|
126
|
+
|
|
127
|
+
requireIncludes("init/xinyun-ai-init/templates/core-rules.template.md", [
|
|
128
|
+
"标准改动计划",
|
|
129
|
+
"前端改动模式:样式微调 / 新页面 / 页面重写 / 组件重构 / 不涉及",
|
|
130
|
+
"有 CodeGraph 时,结构性问题优先使用 CodeGraph",
|
|
131
|
+
"发现可复用经验时,先记录为候选经验",
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function verifyFrameworkRules() {
|
|
136
|
+
const required = [
|
|
137
|
+
"init/xinyun-ai-init/rules/frameworks/README.md",
|
|
138
|
+
"init/xinyun-ai-init/rules/frameworks/backend/php/thinkphp.md",
|
|
139
|
+
"init/xinyun-ai-init/rules/frameworks/frontend/uni-app.md",
|
|
140
|
+
"init/xinyun-ai-init/rules/frameworks/frontend/wechat-miniprogram.md",
|
|
141
|
+
];
|
|
142
|
+
|
|
143
|
+
for (const file of required) {
|
|
144
|
+
requireFile(file);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
requireIncludes("init/xinyun-ai-init/rules/frameworks/backend/php/thinkphp.md", [
|
|
148
|
+
"topthink/framework",
|
|
149
|
+
"think\\facade",
|
|
150
|
+
]);
|
|
151
|
+
requireIncludes("init/xinyun-ai-init/rules/frameworks/frontend/uni-app.md", [
|
|
152
|
+
"pages.json",
|
|
153
|
+
"vite-plugin-uni",
|
|
154
|
+
]);
|
|
155
|
+
requireIncludes("init/xinyun-ai-init/rules/frameworks/frontend/wechat-miniprogram.md", [
|
|
156
|
+
"project.config.json",
|
|
157
|
+
".wxml",
|
|
158
|
+
]);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
function verifyJsonAndMarkdown() {
|
|
162
|
+
const jsonFiles = walkFiles(initRoot).filter((filePath) => filePath.endsWith(".json"));
|
|
163
|
+
const mdFiles = walkFiles(initRoot).filter((filePath) => filePath.endsWith(".md"));
|
|
164
|
+
|
|
165
|
+
for (const filePath of jsonFiles) {
|
|
166
|
+
requireJson(rel(filePath));
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
for (const filePath of mdFiles) {
|
|
170
|
+
requireMarkdownBalanced(rel(filePath));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function main() {
|
|
175
|
+
requireFile("bin/xinyun-ai-init.js");
|
|
176
|
+
requireFile("init/xinyun-ai-init/README.md");
|
|
177
|
+
requireFile("init/xinyun-ai-init/version.json");
|
|
178
|
+
|
|
179
|
+
verifyPackageFiles();
|
|
180
|
+
verifyCliBoundary();
|
|
181
|
+
verifyInitRules();
|
|
182
|
+
verifyFrameworkRules();
|
|
183
|
+
verifyJsonAndMarkdown();
|
|
184
|
+
|
|
185
|
+
const failed = checks.filter((check) => !check.ok);
|
|
186
|
+
|
|
187
|
+
for (const check of checks) {
|
|
188
|
+
const prefix = check.ok ? "[PASS]" : "[FAIL]";
|
|
189
|
+
console.log(`${prefix} ${check.name}`);
|
|
190
|
+
if (!check.ok && check.detail) {
|
|
191
|
+
console.log(` ${check.detail}`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
console.log("");
|
|
196
|
+
console.log(`[xinyun-ai-init verify] ${checks.length - failed.length}/${checks.length} checks passed.`);
|
|
197
|
+
|
|
198
|
+
if (failed.length > 0) {
|
|
199
|
+
process.exit(1);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
main();
|