@qilitt-mickey/vue3-temp-skill 1.1.32 → 1.1.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +92 -33
- package/SKILL.md +84 -236
- package/bin/cli.js +31 -34
- package/package.json +5 -13
- package/references/code-quality.md +17 -117
- package/references/core-kernel.md +4 -1
- package/references/design-handoff.md +34 -63
- package/references/design-system.md +25 -0
- package/references/design-verify.md +6 -6
- package/references/project-inventory.md +431 -431
- package/scripts/check.cmd +7 -5
- package/scripts/check.mjs +10 -21
- package/scripts/cli.mjs +15 -58
- package/scripts/handoff.mjs +108 -0
- package/scripts/match.py +81 -270
- package/scripts/modules.json +92 -347
- package/scripts/validate.mjs +68 -218
- package/references/handoff-governance.md +0 -74
- package/scripts/ai-content-audit.mjs +0 -244
- package/scripts/ai-match-audit.mjs +0 -348
- package/scripts/ai-workflow-sim.mjs +0 -393
- package/scripts/analyze-deps.mjs +0 -278
- package/scripts/generate-index.mjs +0 -214
- package/scripts/handoff-governance.mjs +0 -77
- package/scripts/handoff-lib.mjs +0 -128
- package/scripts/handoff-session-init.mjs +0 -71
- package/scripts/handoff-spec-check.mjs +0 -195
- package/scripts/handoff-step-check.mjs +0 -81
- package/scripts/scaffold-module.mjs +0 -232
package/scripts/check.cmd
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
@echo off
|
|
2
|
-
REM
|
|
3
|
-
where node >nul 2>&1
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
REM Pre-publish checks (ASCII-only wrapper for cmd.exe)
|
|
3
|
+
where node >nul 2>&1
|
|
4
|
+
if errorlevel 1 (
|
|
5
|
+
echo Node.js not found. Add Node.js to PATH.
|
|
6
|
+
exit /b 1
|
|
7
7
|
)
|
|
8
|
+
node "%~dp0check.mjs" %*
|
|
9
|
+
exit /b %ERRORLEVEL%
|
package/scripts/check.mjs
CHANGED
|
@@ -16,31 +16,18 @@ import { fileURLToPath } from "url";
|
|
|
16
16
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
17
17
|
const ROOT = path.resolve(__dirname, "..");
|
|
18
18
|
const NODE = process.execPath;
|
|
19
|
+
const PYTHON = process.env.VUE3_SKILL_PYTHON || (process.platform === "win32" ? "py" : "python3");
|
|
20
|
+
const PYTHON_ARGS = process.platform === "win32" && !process.env.VUE3_SKILL_PYTHON ? ["-3"] : [];
|
|
19
21
|
|
|
20
22
|
const checks = [
|
|
21
23
|
{
|
|
22
24
|
name: "结构校验",
|
|
23
|
-
desc: "frontmatter
|
|
25
|
+
desc: "frontmatter、路由引用、交叉引用",
|
|
24
26
|
cmd: () => run(NODE, "scripts/validate.mjs"),
|
|
25
27
|
},
|
|
26
28
|
{
|
|
27
|
-
name: "
|
|
28
|
-
desc: "
|
|
29
|
-
cmd: () => run(NODE, "scripts/ai-match-audit.mjs"),
|
|
30
|
-
},
|
|
31
|
-
{
|
|
32
|
-
name: "内容可用性",
|
|
33
|
-
desc: "样板完整性、Must-do 清单、代码块完备性",
|
|
34
|
-
cmd: () => run(NODE, "scripts/ai-content-audit.mjs"),
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
name: "依赖图",
|
|
38
|
-
desc: "断链引用、循环依赖、引用热度、孤立模块",
|
|
39
|
-
cmd: () => run(NODE, "scripts/analyze-deps.mjs"),
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
name: "匹配器批量测试",
|
|
43
|
-
desc: "15 个典型场景模块命中验证",
|
|
29
|
+
name: "匹配器回归",
|
|
30
|
+
desc: "高频 Demo 场景能力组命中验证",
|
|
44
31
|
cmd: () => run("python", "scripts/match.py", ["--batch"]),
|
|
45
32
|
},
|
|
46
33
|
];
|
|
@@ -48,7 +35,7 @@ const checks = [
|
|
|
48
35
|
function run(runner, script, args = []) {
|
|
49
36
|
const scriptPath = path.join(ROOT, script);
|
|
50
37
|
if (runner === "python") {
|
|
51
|
-
return execFileSync(
|
|
38
|
+
return execFileSync(PYTHON, [...PYTHON_ARGS, scriptPath, ...args], {
|
|
52
39
|
cwd: ROOT,
|
|
53
40
|
encoding: "utf-8",
|
|
54
41
|
stdio: "pipe",
|
|
@@ -70,8 +57,10 @@ for (const check of checks) {
|
|
|
70
57
|
const output = check.cmd();
|
|
71
58
|
// 只在有输出时打印(避免刷屏)
|
|
72
59
|
const lines = output.trim().split("\n");
|
|
73
|
-
const summary =
|
|
74
|
-
|
|
60
|
+
const summary =
|
|
61
|
+
lines.find((l) => /^OK \d+\/\d+ scenarios/.test(l.trim())) ||
|
|
62
|
+
lines.find((l) => l.includes("校验通过")) ||
|
|
63
|
+
lines[lines.length - 1];
|
|
75
64
|
console.log(`\u2713 ${summary?.trim() || "OK"}`);
|
|
76
65
|
passed++;
|
|
77
66
|
} catch (e) {
|
package/scripts/cli.mjs
CHANGED
|
@@ -6,14 +6,8 @@
|
|
|
6
6
|
* 用法:
|
|
7
7
|
* node scripts/cli.mjs # 等同 --validate
|
|
8
8
|
* node scripts/cli.mjs --validate # 结构校验
|
|
9
|
-
* node scripts/cli.mjs --audit # 命中精度审计
|
|
10
|
-
* node scripts/cli.mjs --content # 内容可用性审计
|
|
11
|
-
* node scripts/cli.mjs --sim # 工作流模拟
|
|
12
|
-
* node scripts/cli.mjs --deps # 依赖图分析
|
|
13
9
|
* node scripts/cli.mjs --route "<需求>" # 路由测试
|
|
14
|
-
* node scripts/cli.mjs --
|
|
15
|
-
* node scripts/cli.mjs --scaffold <name> # 新建模块骨架
|
|
16
|
-
* node scripts/cli.mjs --all # 全量审计(validate + audit + content + deps)
|
|
10
|
+
* node scripts/cli.mjs --all # 最小发布检查(validate + match batch)
|
|
17
11
|
* node scripts/cli.mjs --list # 列出所有命令
|
|
18
12
|
*
|
|
19
13
|
* 运行时匹配器(AI 调用):
|
|
@@ -21,13 +15,15 @@
|
|
|
21
15
|
* python scripts/match.py --batch
|
|
22
16
|
*/
|
|
23
17
|
|
|
24
|
-
import {
|
|
18
|
+
import { execFileSync } from "child_process";
|
|
25
19
|
import path from "path";
|
|
26
20
|
import { fileURLToPath } from "url";
|
|
27
21
|
|
|
28
22
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
29
23
|
const ROOT = path.resolve(__dirname, "..");
|
|
30
24
|
const NODE = process.execPath;
|
|
25
|
+
const PYTHON = process.env.VUE3_SKILL_PYTHON || "python";
|
|
26
|
+
const PYTHON_ARGS = [];
|
|
31
27
|
|
|
32
28
|
const commands = {
|
|
33
29
|
validate: {
|
|
@@ -35,50 +31,15 @@ const commands = {
|
|
|
35
31
|
file: "validate.mjs",
|
|
36
32
|
args: [],
|
|
37
33
|
},
|
|
38
|
-
audit: {
|
|
39
|
-
desc: "命中精度审计:关键词重叠、命中盲区、模块评分、边界冲突",
|
|
40
|
-
file: "ai-match-audit.mjs",
|
|
41
|
-
args: [],
|
|
42
|
-
},
|
|
43
|
-
content: {
|
|
44
|
-
desc: "内容可用性审计:样板完整性、Must-do 清单、代码块完备性",
|
|
45
|
-
file: "ai-content-audit.mjs",
|
|
46
|
-
args: [],
|
|
47
|
-
},
|
|
48
|
-
sim: {
|
|
49
|
-
desc: "AI 工作流模拟:6 步端到端验证",
|
|
50
|
-
file: "ai-workflow-sim.mjs",
|
|
51
|
-
args: [],
|
|
52
|
-
},
|
|
53
|
-
deps: {
|
|
54
|
-
desc: "依赖图分析:断链引用、循环依赖、引用热度、孤立模块",
|
|
55
|
-
file: "analyze-deps.mjs",
|
|
56
|
-
args: [],
|
|
57
|
-
},
|
|
58
34
|
route: {
|
|
59
35
|
desc: "路由测试:对自然语言需求进行模块命中分析(使用 match.py)",
|
|
60
36
|
cmd: "python",
|
|
61
37
|
file: "match.py",
|
|
62
38
|
args: "pass",
|
|
63
39
|
},
|
|
64
|
-
|
|
65
|
-
desc: "
|
|
66
|
-
file: "
|
|
67
|
-
args: [],
|
|
68
|
-
},
|
|
69
|
-
scaffold: {
|
|
70
|
-
desc: "新建模块骨架:自动生成 frontmatter + 标准结构",
|
|
71
|
-
file: "scaffold-module.mjs",
|
|
72
|
-
args: "pass",
|
|
73
|
-
},
|
|
74
|
-
"handoff-init": {
|
|
75
|
-
desc: "设计落地:初始化业务项目 .handoff/session.json",
|
|
76
|
-
file: "handoff-session-init.mjs",
|
|
77
|
-
args: "pass",
|
|
78
|
-
},
|
|
79
|
-
"handoff-check": {
|
|
80
|
-
desc: "设计落地:管控闸门(步骤 + JSON 规格)",
|
|
81
|
-
file: "handoff-governance.mjs",
|
|
40
|
+
handoff: {
|
|
41
|
+
desc: "设计交接:初始化或检查 handoff 状态",
|
|
42
|
+
file: "handoff.mjs",
|
|
82
43
|
args: "pass",
|
|
83
44
|
},
|
|
84
45
|
};
|
|
@@ -90,14 +51,10 @@ function run(cmd, extraArgs = []) {
|
|
|
90
51
|
process.exit(1);
|
|
91
52
|
}
|
|
92
53
|
const scriptPath = path.join(__dirname, cfg.file);
|
|
93
|
-
const runner = cfg.cmd === "python" ? "python" : `"${NODE}"`;
|
|
94
|
-
const quotedArgs = extraArgs.map(a => a.includes(" ") ? `"${a}"` : a).join(" ");
|
|
95
54
|
try {
|
|
96
|
-
const result =
|
|
97
|
-
cwd: ROOT,
|
|
98
|
-
encoding: "utf-8",
|
|
99
|
-
stdio: "pipe",
|
|
100
|
-
});
|
|
55
|
+
const result = cfg.cmd === "python"
|
|
56
|
+
? execFileSync(PYTHON, [...PYTHON_ARGS, scriptPath, ...extraArgs], { cwd: ROOT, encoding: "utf-8", stdio: "pipe" })
|
|
57
|
+
: execFileSync(NODE, [scriptPath, ...extraArgs], { cwd: ROOT, encoding: "utf-8", stdio: "pipe" });
|
|
101
58
|
console.log(result);
|
|
102
59
|
} catch (e) {
|
|
103
60
|
if (e.stdout) console.log(e.stdout);
|
|
@@ -109,14 +66,14 @@ function run(cmd, extraArgs = []) {
|
|
|
109
66
|
function listCommands() {
|
|
110
67
|
console.log("\nvue3-temp-skill 脚本命令\n");
|
|
111
68
|
console.log("运行时匹配器(AI 调用):");
|
|
112
|
-
console.log(
|
|
113
|
-
console.log(
|
|
69
|
+
console.log(` ${process.platform === "win32" ? "py -3" : "python3"} scripts/match.py \"<需求>\" # 获取精确模块匹配`);
|
|
70
|
+
console.log(` ${process.platform === "win32" ? "py -3" : "python3"} scripts/match.py --batch # 批量测试 15 场景\n`);
|
|
114
71
|
console.log("开发与审计命令:");
|
|
115
72
|
for (const [cmd, cfg] of Object.entries(commands)) {
|
|
116
73
|
const argHint = cfg.args === "pass" ? " <参数>" : "";
|
|
117
|
-
console.log(` node scripts/cli.mjs --${cmd.padEnd(10)} ${cfg.desc}`);
|
|
74
|
+
console.log(` node scripts/cli.mjs --${cmd.padEnd(10)}${argHint} ${cfg.desc}`);
|
|
118
75
|
}
|
|
119
|
-
console.log(` node scripts/cli.mjs --all
|
|
76
|
+
console.log(` node scripts/cli.mjs --all 最小发布检查(validate)`);
|
|
120
77
|
console.log(` node scripts/cli.mjs --list 列出所有命令\n`);
|
|
121
78
|
}
|
|
122
79
|
|
|
@@ -141,7 +98,7 @@ switch (flag) {
|
|
|
141
98
|
|
|
142
99
|
case "all": {
|
|
143
100
|
console.log("=== 全量审计 ===\n");
|
|
144
|
-
for (const cmd of ["validate"
|
|
101
|
+
for (const cmd of ["validate"]) {
|
|
145
102
|
console.log(`\n--- ${cmd} ---\n`);
|
|
146
103
|
try {
|
|
147
104
|
run(cmd);
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 设计交接的轻量工具。
|
|
5
|
+
*
|
|
6
|
+
* init: 校验 design-handoff/v1 并把状态放在用户目录。
|
|
7
|
+
* check: 校验状态和目标项目的关键接线,不要求无关文件全部变更。
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
11
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
|
+
import os from "node:os";
|
|
13
|
+
import path from "node:path";
|
|
14
|
+
import { execFileSync } from "node:child_process";
|
|
15
|
+
import { fileURLToPath } from "node:url";
|
|
16
|
+
|
|
17
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
18
|
+
const STATE_ROOT = path.join(os.homedir(), ".workbuddy", "state", "vue3-temp-skill");
|
|
19
|
+
|
|
20
|
+
function parseArgs(argv) {
|
|
21
|
+
const result = { project: process.cwd(), file: null, stateDir: null, requireSession: false };
|
|
22
|
+
for (let i = 0; i < argv.length; i++) {
|
|
23
|
+
const arg = argv[i];
|
|
24
|
+
if (arg === "--project" && argv[i + 1]) result.project = path.resolve(argv[++i]);
|
|
25
|
+
else if (arg === "--file" && argv[i + 1]) result.file = path.resolve(argv[++i]);
|
|
26
|
+
else if (arg === "--state-dir" && argv[i + 1]) result.stateDir = path.resolve(argv[++i]);
|
|
27
|
+
else if (arg === "--require-session") result.requireSession = true;
|
|
28
|
+
}
|
|
29
|
+
const projectId = createHash("sha256").update(result.project.toLowerCase()).digest("hex").slice(0, 16);
|
|
30
|
+
result.stateDir ||= path.join(STATE_ROOT, projectId);
|
|
31
|
+
result.sessionPath = path.join(result.stateDir, "handoff.json");
|
|
32
|
+
return result;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function readJson(file) {
|
|
36
|
+
try {
|
|
37
|
+
// 设计工具导出的 JSON 常带 UTF-8 BOM,直接 parse 会失败
|
|
38
|
+
const raw = readFileSync(file, "utf8").replace(/^\uFEFF/, "");
|
|
39
|
+
return JSON.parse(raw);
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function validateHandoff(handoff) {
|
|
46
|
+
const errors = [];
|
|
47
|
+
if (handoff?.$schema !== "design-handoff/v1") errors.push("需要 $schema: design-handoff/v1");
|
|
48
|
+
for (const key of ["meta", "shell", "geometry", "tokens"]) {
|
|
49
|
+
if (!handoff?.[key]) errors.push(`缺少 ${key}`);
|
|
50
|
+
}
|
|
51
|
+
if (handoff?.structureRequirements && !handoff?.interactionSpecs) errors.push("有 structureRequirements 时必须同时提供 interactionSpecs");
|
|
52
|
+
if (handoff?.tokens?.primaryScale && handoff.tokens.primaryScale.length !== 10) errors.push("tokens.primaryScale 必须为 10 项");
|
|
53
|
+
return errors;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function projectChecks(project, handoff) {
|
|
57
|
+
const checks = [];
|
|
58
|
+
const required = [
|
|
59
|
+
"package.json",
|
|
60
|
+
"src/layout/components/lay-navbar/index.vue",
|
|
61
|
+
"src/layout/components/lay-tag/index.vue",
|
|
62
|
+
];
|
|
63
|
+
for (const rel of required) checks.push({ rel, ok: existsSync(path.join(project, rel)) });
|
|
64
|
+
if (handoff?.tokens) checks.push({ rel: "src/styles/design-tokens.scss", ok: existsSync(path.join(project, "src/styles/design-tokens.scss")) });
|
|
65
|
+
return checks;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function init(args) {
|
|
69
|
+
if (!args.file) throw new Error("handoff init 需要 --file <handoff.json>");
|
|
70
|
+
if (!existsSync(args.file)) throw new Error(`找不到 handoff 文件:${args.file}`);
|
|
71
|
+
const handoff = readJson(args.file);
|
|
72
|
+
if (handoff === null) throw new Error(`handoff 文件不是合法 JSON:${args.file}`);
|
|
73
|
+
const errors = validateHandoff(handoff);
|
|
74
|
+
if (errors.length) throw new Error(`handoff JSON 无效:${errors.join(";")}`);
|
|
75
|
+
mkdirSync(args.stateDir, { recursive: true });
|
|
76
|
+
writeFileSync(args.sessionPath, JSON.stringify({ version: 1, project: args.project, createdAt: new Date().toISOString(), handoff }, null, 2), "utf8");
|
|
77
|
+
console.log(`✓ 已初始化设计交接状态:${args.sessionPath}`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function check(args) {
|
|
81
|
+
if (!existsSync(args.sessionPath)) {
|
|
82
|
+
if (args.requireSession) throw new Error("没有设计交接状态,请先执行 handoff init");
|
|
83
|
+
console.log("无设计交接状态,跳过检查");
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
const state = readJson(args.sessionPath);
|
|
87
|
+
const errors = validateHandoff(state?.handoff);
|
|
88
|
+
const checks = projectChecks(args.project, state?.handoff);
|
|
89
|
+
const missing = checks.filter(item => !item.ok).map(item => item.rel);
|
|
90
|
+
if (missing.length) errors.push(`目标项目缺少关键文件:${missing.join(", ")}`);
|
|
91
|
+
if (errors.length) throw new Error(`handoff 检查失败:${errors.join(";")}`);
|
|
92
|
+
console.log(`✓ handoff 检查通过:${checks.length} 个关键接线已确认`);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function main() {
|
|
96
|
+
const [command = "check", ...rest] = process.argv.slice(2);
|
|
97
|
+
const args = parseArgs(rest);
|
|
98
|
+
if (command === "init") init(args);
|
|
99
|
+
else if (command === "check") check(args);
|
|
100
|
+
else throw new Error("用法:node scripts/handoff.mjs init|check --project <项目> [--file <handoff.json>] [--require-session]");
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
try {
|
|
104
|
+
main();
|
|
105
|
+
} catch (error) {
|
|
106
|
+
console.error(`✗ ${error.message}`);
|
|
107
|
+
process.exit(1);
|
|
108
|
+
}
|