skill-forge-hub 0.2.0 → 0.4.0
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 +28 -6
- package/annual-report/SKILL.md +24 -9
- package/annual-report/resources/content-rules.md +11 -9
- package/annual-report/resources/data-collection.md +3 -3
- package/annual-report/resources/date-parsing.md +1 -1
- package/annual-report/resources/disk-and-html.md +8 -6
- package/annual-report/resources/industry-dictionary.md +3 -1
- package/annual-report/resources/reference.html +360 -0
- package/annual-report/resources/usage-guide.md +56 -15
- package/annual-report/user-config.md +4 -1
- package/cli.js +176 -36
- package/daily-report/SKILL.md +24 -8
- package/daily-report/resources/content-rules.md +34 -30
- package/daily-report/resources/data-collection.md +5 -5
- package/daily-report/resources/date-parsing.md +1 -1
- package/daily-report/resources/disk-and-html.md +4 -2
- package/daily-report/resources/industry-dictionary.md +3 -1
- package/daily-report/resources/reference.html +617 -0
- package/daily-report/resources/usage-guide.md +14 -14
- package/daily-report/user-config.md +6 -3
- package/magic-deck/SKILL.md +52 -0
- package/magic-deck/resources/deck-spec.md +259 -0
- package/magic-deck/resources/reference.html +973 -0
- package/magic-deck/user-config.md +37 -0
- package/meta-forge/SKILL.md +46 -0
- package/meta-forge/resources/forge-rules.md +74 -0
- package/meta-forge/resources/usage-guide.md +41 -0
- package/meta-forge/user-config.md +19 -0
- package/package.json +3 -1
- package/spec-doc2spec/SKILL.md +17 -8
- package/spec-doc2spec/user-config.md +22 -0
- package/spec-spec2doc/SKILL.md +17 -8
- package/spec-spec2doc/user-config.md +22 -0
- package/weekly-report/SKILL.md +24 -8
- package/weekly-report/resources/content-rules.md +43 -32
- package/weekly-report/resources/data-collection.md +5 -5
- package/weekly-report/resources/date-parsing.md +1 -1
- package/weekly-report/resources/disk-and-html.md +4 -2
- package/weekly-report/resources/industry-dictionary.md +5 -3
- package/weekly-report/resources/reference.html +899 -0
- package/weekly-report/resources/usage-guide.md +15 -15
- package/weekly-report/user-config.md +6 -3
package/cli.js
CHANGED
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
/**
|
|
4
4
|
* SkillForge CLI —— 技能锻造坊安装器
|
|
5
5
|
*
|
|
6
|
-
* skill-forge ls
|
|
7
|
-
* skill-forge init
|
|
6
|
+
* skill-forge ls 列出全部技能(分类 + 名称 + 说明)
|
|
7
|
+
* skill-forge init 交互式挑选技能,装进 AI 助手的技能目录
|
|
8
|
+
* skill-forge update 升级已安装技能(配置版本感知:官方配置结构变化时
|
|
9
|
+
* 先备份你的配置,再询问覆盖/保留/稍后处理)
|
|
8
10
|
*
|
|
9
11
|
* 零依赖,Node >= 14。
|
|
10
12
|
*/
|
|
@@ -21,6 +23,9 @@ const CATEGORIES = [
|
|
|
21
23
|
{ name: "报表汇演", en: "Reports", skills: ["daily-report", "weekly-report", "annual-report"] },
|
|
22
24
|
{ name: "文档装裱", en: "Documents", skills: ["article-to-html"] },
|
|
23
25
|
{ name: "工程提效", en: "Engineering", skills: ["spec-doc2spec", "spec-spec2doc"] },
|
|
26
|
+
{ name: "演示汇演", en: "Slides", skills: ["magic-deck"] },
|
|
27
|
+
{ name: "沟通协作", en: "Communication", skills: ["prompt-pouch"] },
|
|
28
|
+
{ name: "技能自造", en: "Meta", skills: ["meta-forge"] },
|
|
24
29
|
];
|
|
25
30
|
|
|
26
31
|
// 常见 AI 助手的用户级技能目录(宿主中立,init 时自动探测)
|
|
@@ -111,13 +116,35 @@ function loadPreserveSet(skillDir) {
|
|
|
111
116
|
return set;
|
|
112
117
|
}
|
|
113
118
|
|
|
114
|
-
|
|
119
|
+
// 解析 user-config.md 首行 yaml 的 CONFIG_VERSION(缺失视为 0=未声明版本)
|
|
120
|
+
function parseUserConfigVersion(file) {
|
|
121
|
+
if (!fs.existsSync(file)) return 0;
|
|
122
|
+
const m = fs.readFileSync(file, "utf8").match(/^CONFIG_VERSION:\s*(\d+)/m);
|
|
123
|
+
return m ? parseInt(m[1], 10) : 0;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function stamp() {
|
|
127
|
+
const d = new Date();
|
|
128
|
+
const p = (n) => String(n).padStart(2, "0");
|
|
129
|
+
return "" + d.getFullYear() + p(d.getMonth() + 1) + p(d.getDate()) + "-" + p(d.getHours()) + p(d.getMinutes()) + p(d.getSeconds());
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function copyDir(src, dest, preserve, hits, upstreams) {
|
|
115
133
|
fs.mkdirSync(dest, { recursive: true });
|
|
116
134
|
for (const entry of fs.readdirSync(src)) {
|
|
117
135
|
const s = path.join(src, entry);
|
|
118
136
|
const d = path.join(dest, entry);
|
|
119
|
-
if (fs.statSync(s).isDirectory()) copyDir(s, d, preserve, hits);
|
|
120
|
-
else if (preserve.has(entry.toLowerCase()) && fs.existsSync(d))
|
|
137
|
+
if (fs.statSync(s).isDirectory()) copyDir(s, d, preserve, hits, upstreams);
|
|
138
|
+
else if (preserve.has(entry.toLowerCase()) && fs.existsSync(d)) {
|
|
139
|
+
hits.push(d);
|
|
140
|
+
// 配置演进:官方版与本地版内容不同时,另存 .upstream 对照文件,供用户手动合并新配置点
|
|
141
|
+
const sData = fs.readFileSync(s, "utf8");
|
|
142
|
+
const dData = fs.readFileSync(d, "utf8");
|
|
143
|
+
if (sData !== dData) {
|
|
144
|
+
fs.writeFileSync(d + ".upstream", sData);
|
|
145
|
+
upstreams.push(d + ".upstream");
|
|
146
|
+
}
|
|
147
|
+
}
|
|
121
148
|
else fs.copyFileSync(s, d);
|
|
122
149
|
}
|
|
123
150
|
}
|
|
@@ -214,6 +241,83 @@ async function selectSkillsInteractive(skills) {
|
|
|
214
241
|
return chosen;
|
|
215
242
|
}
|
|
216
243
|
|
|
244
|
+
// 解析目标技能目录(--target 优先,否则自动探测;失败返回 null)
|
|
245
|
+
async function resolveTarget(argv, cmd) {
|
|
246
|
+
if (argv.target) return expandHome(argv.target);
|
|
247
|
+
const detected = detectTargetDirs();
|
|
248
|
+
if (detected.length === 1) {
|
|
249
|
+
console.log(`检测到技能目录:${detected[0]}`);
|
|
250
|
+
return detected[0];
|
|
251
|
+
}
|
|
252
|
+
if (detected.length > 1 && process.stdin.isTTY) {
|
|
253
|
+
console.log("检测到多个技能目录:");
|
|
254
|
+
detected.forEach((d, i) => console.log(` [${i + 1}] ${d}`));
|
|
255
|
+
const ans = await ask("选择目标目录编号(回车取第一个):");
|
|
256
|
+
const i = parseInt(ans, 10) - 1;
|
|
257
|
+
return detected[isNaN(i) || i < 0 || i >= detected.length ? 0 : i];
|
|
258
|
+
}
|
|
259
|
+
if (detected.length > 1) {
|
|
260
|
+
console.log(`检测到多个技能目录,非交互环境取第一个:${detected[0]}`);
|
|
261
|
+
return detected[0];
|
|
262
|
+
}
|
|
263
|
+
console.log("未检测到常见 AI 助手的技能目录。");
|
|
264
|
+
console.log(`请用 --target 指定,例如:skill-forge ${cmd} --target ~/.claude/skills`);
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// 升级单个技能:配置版本感知(官方 CONFIG_VERSION > 本地时备份并询问),返回展示注记
|
|
269
|
+
async function upgradeSkill(src, dest, argv, existed) {
|
|
270
|
+
const hits = [];
|
|
271
|
+
const upstreams = [];
|
|
272
|
+
let mode = "preserve"; // preserve=保留我的 | official=官方覆盖 | later=稍后处理
|
|
273
|
+
let bakFile = null;
|
|
274
|
+
|
|
275
|
+
const officialCfg = path.join(src, "user-config.md");
|
|
276
|
+
const localCfg = path.join(dest, "user-config.md");
|
|
277
|
+
if (existed && fs.existsSync(officialCfg) && fs.existsSync(localCfg)) {
|
|
278
|
+
const officialVer = parseUserConfigVersion(officialCfg);
|
|
279
|
+
const localVer = parseUserConfigVersion(localCfg);
|
|
280
|
+
if (officialVer > localVer) {
|
|
281
|
+
bakFile = localCfg + ".bak-" + stamp();
|
|
282
|
+
fs.copyFileSync(localCfg, bakFile);
|
|
283
|
+
console.log(`\n⚠️ ${path.basename(dest)} 配置结构升级:官方 v${officialVer} > 你的 v${localVer}`);
|
|
284
|
+
console.log(` 已备份你的配置:${path.basename(bakFile)}`);
|
|
285
|
+
if (process.stdin.isTTY && !argv.yes) {
|
|
286
|
+
console.log(" [1] 官方覆盖 —— 用官方新配置替换(旧配置在备份中,随时找回)");
|
|
287
|
+
console.log(" [2] 保留我的 —— 不覆盖,官方新配置另存 .upstream 对照(默认)");
|
|
288
|
+
console.log(" [3] 稍后处理 —— 本次只升级技能文件,配置改天自己合并");
|
|
289
|
+
const ans = await ask(" 你的选择(回车默认 2):");
|
|
290
|
+
if (ans === "1") mode = "official";
|
|
291
|
+
else if (ans === "3") mode = "later";
|
|
292
|
+
} else {
|
|
293
|
+
console.log(" 非交互/--yes:默认保留你的配置,官方新版另存 .upstream 对照");
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
if (mode === "official") fs.unlinkSync(localCfg); // 备份已做,移除后 copyDir 正常覆盖
|
|
299
|
+
copyDir(src, dest, loadPreserveSet(src), hits, upstreams);
|
|
300
|
+
|
|
301
|
+
let note = existed ? "已更新" : "已安装";
|
|
302
|
+
if (mode === "official") {
|
|
303
|
+
note += `(已用官方配置覆盖,你的旧配置备份在 ${path.basename(bakFile)})`;
|
|
304
|
+
} else if (bakFile) {
|
|
305
|
+
const ups = upstreams.map((u) => path.basename(u)).join("、");
|
|
306
|
+
note += `(配置结构有变:你的配置已备份 ${path.basename(bakFile)}` +
|
|
307
|
+
(ups ? ` + 官方版对照 ${ups}` : "") + ",请手动合并)";
|
|
308
|
+
} else {
|
|
309
|
+
if (hits.length > 0) {
|
|
310
|
+
const names = hits.map((h) => path.basename(h)).join("、");
|
|
311
|
+
note += `(保留你的本地修改未覆盖:${names})`;
|
|
312
|
+
}
|
|
313
|
+
if (upstreams.length > 0) {
|
|
314
|
+
const names = upstreams.map((u) => path.basename(u)).join("、");
|
|
315
|
+
note += `;官方配置有更新,已另存对照文件:${names}(可手动合并新配置点)`;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
return note;
|
|
319
|
+
}
|
|
320
|
+
|
|
217
321
|
async function cmdInit(argv) {
|
|
218
322
|
const skills = scanSkills();
|
|
219
323
|
if (skills.length === 0) {
|
|
@@ -222,27 +326,8 @@ async function cmdInit(argv) {
|
|
|
222
326
|
}
|
|
223
327
|
|
|
224
328
|
// 1. 目标目录
|
|
225
|
-
|
|
226
|
-
if (!target)
|
|
227
|
-
const detected = detectTargetDirs();
|
|
228
|
-
if (detected.length === 1) {
|
|
229
|
-
target = detected[0];
|
|
230
|
-
console.log(`检测到技能目录:${target}`);
|
|
231
|
-
} else if (detected.length > 1 && process.stdin.isTTY) {
|
|
232
|
-
console.log("检测到多个技能目录:");
|
|
233
|
-
detected.forEach((d, i) => console.log(` [${i + 1}] ${d}`));
|
|
234
|
-
const ans = await ask("选择目标目录编号(回车取第一个):");
|
|
235
|
-
const i = parseInt(ans, 10) - 1;
|
|
236
|
-
target = detected[isNaN(i) || i < 0 || i >= detected.length ? 0 : i];
|
|
237
|
-
} else if (detected.length > 1) {
|
|
238
|
-
target = detected[0];
|
|
239
|
-
console.log(`检测到多个技能目录,非交互环境取第一个:${target}`);
|
|
240
|
-
} else {
|
|
241
|
-
console.log("未检测到常见 AI 助手的技能目录。");
|
|
242
|
-
console.log("请用 --target 指定,例如:skill-forge init --target ~/.claude/skills");
|
|
243
|
-
return;
|
|
244
|
-
}
|
|
245
|
-
}
|
|
329
|
+
const target = await resolveTarget(argv, "init");
|
|
330
|
+
if (!target) return;
|
|
246
331
|
|
|
247
332
|
// 2. 选择技能
|
|
248
333
|
let chosen;
|
|
@@ -277,23 +362,70 @@ async function cmdInit(argv) {
|
|
|
277
362
|
}
|
|
278
363
|
}
|
|
279
364
|
|
|
280
|
-
// 4.
|
|
365
|
+
// 4. 复制(已存在的走版本感知升级)
|
|
281
366
|
for (const s of chosen) {
|
|
282
367
|
const src = path.join(PKG_DIR, s.dir);
|
|
283
368
|
const dest = path.join(target, s.dir);
|
|
284
|
-
const
|
|
285
|
-
const hits = [];
|
|
286
|
-
copyDir(src, dest, loadPreserveSet(src), hits);
|
|
287
|
-
let note = existed ? "已更新" : "已安装";
|
|
288
|
-
if (hits.length > 0) {
|
|
289
|
-
const names = hits.map((h) => path.basename(h)).join("、");
|
|
290
|
-
note += `(保留你的本地修改未覆盖:${names})`;
|
|
291
|
-
}
|
|
369
|
+
const note = await upgradeSkill(src, dest, argv, fs.existsSync(dest));
|
|
292
370
|
console.log(`${note}:${s.name} → ${dest}`);
|
|
293
371
|
}
|
|
294
372
|
console.log(`\n完成。共 ${chosen.length} 件技能。`);
|
|
295
373
|
}
|
|
296
374
|
|
|
375
|
+
// ---------- update ----------
|
|
376
|
+
|
|
377
|
+
async function cmdUpdate(argv) {
|
|
378
|
+
const skills = scanSkills();
|
|
379
|
+
if (skills.length === 0) {
|
|
380
|
+
console.log("未发现任何技能。");
|
|
381
|
+
return;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// 1. 目标目录
|
|
385
|
+
const target = await resolveTarget(argv, "update");
|
|
386
|
+
if (!target) return;
|
|
387
|
+
|
|
388
|
+
// 2. 已安装技能 = 目标目录下存在同名目录且带 SKILL.md
|
|
389
|
+
let installed = [];
|
|
390
|
+
for (const s of skills) {
|
|
391
|
+
if (fs.existsSync(path.join(target, s.dir, "SKILL.md"))) installed.push(s);
|
|
392
|
+
}
|
|
393
|
+
if (argv.skills) {
|
|
394
|
+
const wanted = argv.skills.split(",").map((x) => x.trim());
|
|
395
|
+
installed = installed.filter((s) => wanted.includes(s.name));
|
|
396
|
+
if (installed.length === 0) {
|
|
397
|
+
console.log(`错误:目标目录没有已安装的指定技能。可用 --skills 仅限已装技能,请先 init。`);
|
|
398
|
+
process.exit(1);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
if (installed.length === 0) {
|
|
402
|
+
console.log(`目标目录没有已安装的 SkillForge 技能,请先 init。`);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// 3. 确认
|
|
407
|
+
if (!argv.yes) {
|
|
408
|
+
console.log(`\n将升级 ${installed.length} 件技能:`);
|
|
409
|
+
installed.forEach((s) => console.log(` - ${s.name}`));
|
|
410
|
+
if (process.stdin.isTTY) {
|
|
411
|
+
const ans = await ask("确认升级?(y/N):");
|
|
412
|
+
if (!/^y/i.test(ans)) {
|
|
413
|
+
console.log("已取消。");
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
// 4. 逐个升级(配置版本感知)
|
|
420
|
+
for (const s of installed) {
|
|
421
|
+
const src = path.join(PKG_DIR, s.dir);
|
|
422
|
+
const dest = path.join(target, s.dir);
|
|
423
|
+
const note = await upgradeSkill(src, dest, argv, true);
|
|
424
|
+
console.log(`${note}:${s.name} → ${dest}`);
|
|
425
|
+
}
|
|
426
|
+
console.log(`\n完成。共升级 ${installed.length} 件技能。`);
|
|
427
|
+
}
|
|
428
|
+
|
|
297
429
|
// ---------- 入口 ----------
|
|
298
430
|
|
|
299
431
|
function printHelp() {
|
|
@@ -302,12 +434,19 @@ function printHelp() {
|
|
|
302
434
|
用法:
|
|
303
435
|
skill-forge ls 列出全部技能(分类 + 名称 + 说明)
|
|
304
436
|
skill-forge init 交互式挑选技能并安装到 AI 助手技能目录
|
|
437
|
+
skill-forge update 升级已安装技能(配置版本感知,默认全部已装技能)
|
|
438
|
+
skill-forge update --skills a,b 只升级指定技能
|
|
305
439
|
skill-forge init --target <目录> 指定技能目录(默认自动探测常见助手目录)
|
|
306
440
|
skill-forge init --skills a,b 跳过选择,直接安装指定技能(适合脚本)
|
|
307
441
|
skill-forge init --yes 跳过确认,直接安装
|
|
308
442
|
skill-forge --version 显示版本
|
|
309
443
|
|
|
310
|
-
|
|
444
|
+
升级保护(init/update 均生效):
|
|
445
|
+
· 目标目录已存在的 user-config.md(及技能 .preserve 清单声明的文件)不会被覆盖
|
|
446
|
+
· 官方 user-config.md 的 CONFIG_VERSION 高于你的本地版本(配置结构变化)时:
|
|
447
|
+
先备份你的配置为 user-config.md.bak-<时间戳>,再询问三选一——
|
|
448
|
+
[1] 官方覆盖(备份在侧,随时找回)/ [2] 保留我的 + 官方版另存 .upstream 对照(默认)
|
|
449
|
+
[3] 稍后处理;--yes 或非交互时默认 [2]
|
|
311
450
|
|
|
312
451
|
示例:
|
|
313
452
|
skill-forge ls
|
|
@@ -336,6 +475,7 @@ async function main() {
|
|
|
336
475
|
if (!cmd) return printHelp();
|
|
337
476
|
if (cmd === "ls" || cmd === "list") return cmdLs();
|
|
338
477
|
if (cmd === "init" || cmd === "install") return cmdInit(argv);
|
|
478
|
+
if (cmd === "update" || cmd === "upgrade") return cmdUpdate(argv);
|
|
339
479
|
if (cmd === "--version" || cmd === "-v" || cmd === "version") {
|
|
340
480
|
console.log(VERSION);
|
|
341
481
|
return;
|
package/daily-report/SKILL.md
CHANGED
|
@@ -1,31 +1,47 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: daily-report
|
|
3
|
-
description:
|
|
3
|
+
description: 生成工作日报(默认任务进度/明日计划/风险阻塞点三段结构,中文顿号序号),适配各行业(内置 12 行业职业词典,可指定角色身份)。数据来源灵活:直接口述、给一段文字、发文件(Word/PDF/Excel/PPT 等)或图片,都能整理成日报。支持自定义模板(可永久或临时指定)。支持自然语言指定日期(今天/昨天/上周三/10月20号等)。当用户请求写日报、今日日报、昨天的日报、生成日报、/daily-report,或询问日报用法(日报怎么用/日报使用说明/日报有哪些使用方式)时使用。
|
|
4
4
|
allowed-tools: Bash, Read, Write
|
|
5
5
|
disable-model-invocation: false
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# 日报生成
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
多源数据生成三段式日报(今日任务进度/明日计划/风险阻塞点)——数据来源灵活:一段文字、文件里的描述、图片或口头补充皆可成稿;对话输出 md 正文 + 落盘 md/txt/html/content-png 并自动打开 html。
|
|
11
11
|
|
|
12
12
|
## 生成流程
|
|
13
13
|
|
|
14
|
-
0. **读用户配置**(DISK/FORMATS/DIR/OPEN_HTML/TEMPLATE/ROLE/CONFIRM、自定义模板)→ 先 Read 同目录 `user-config.md`
|
|
14
|
+
0. **读用户配置**(DISK/FORMATS/DIR/OPEN_HTML/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION、自定义模板)→ 先 Read 同目录 `user-config.md`
|
|
15
15
|
1. **解析日期**(自然语言 → 目标日期 YYYY-MM-DD)→ 读 `resources/date-parsing.md`
|
|
16
|
-
2.
|
|
16
|
+
2. **收集数据**(多源:会话口述 / 文字 / 文件 / 图片 / 代码提交记录,合并去重)→ 读 `resources/data-collection.md`
|
|
17
17
|
3. **内容归类与润色**(聚合来源 / 补充任务 / 纯文字模式 / 输出格式 / 写作风格)→ 读 `resources/content-rules.md`
|
|
18
18
|
4. **行业词条**(话术含职业词时按词典取词)→ 读 `resources/industry-dictionary.md`
|
|
19
19
|
5. **落盘与截图**(md/txt/html/content-png + 自动打开 html)→ 读 `resources/disk-and-html.md`
|
|
20
|
-
6. **使用咨询**(用户只问「日报怎么用」等用法、未要求生成)→ 读 `resources/usage-guide.md
|
|
20
|
+
6. **使用咨询**(用户只问「日报怎么用」等用法、未要求生成)→ 读 `resources/usage-guide.md`,将其内容原样输出(首行标题改为「日报生成器使用指南」),不收集数据、不生成报告、不落盘、不开浏览器
|
|
21
21
|
|
|
22
22
|
## ⚙️ 配置与自定义模板
|
|
23
23
|
|
|
24
|
-
**执行本 skill 前必须先 Read 同目录 `user-config.md`**:默认配置(DISK/FORMATS/DIR/OPEN_HTML/TEMPLATE/ROLE/CONFIRM)与自定义模板都在该文件中,以它为准。升级技能时 user-config.md
|
|
24
|
+
**执行本 skill 前必须先 Read 同目录 `user-config.md`**:默认配置(DISK/FORMATS/DIR/OPEN_HTML/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION)与自定义模板都在该文件中,以它为准。升级技能时 user-config.md 不会被覆盖,你的修改永久保留;官方更新配置时另存 `user-config.md.upstream` 对照文件,可按需手动合并新配置点。
|
|
25
|
+
|
|
26
|
+
## 配置版本机制(升级保护)
|
|
27
|
+
|
|
28
|
+
本 skill 当前配置版本为 `1`(对应 user-config.md 中的 `CONFIG_VERSION`)。执行时若发现 user-config.md 的 CONFIG_VERSION 与本节声明的当前版本不一致:
|
|
29
|
+
|
|
30
|
+
1. 先将旧 user-config.md 备份为 `user-config.md.bak-<时间戳>`(同目录,绝不删除旧值)
|
|
31
|
+
2. 按本节「配置升级规则」迁移字段:新增字段补默认值、改名字段按映射改写、删除字段的值保留在备份中并在对话提示用户手动确认
|
|
32
|
+
3. 更新 CONFIG_VERSION 为当前版本
|
|
33
|
+
4. 对话中明确告知用户「检测到配置版本从 X 升级到 Y,旧配置已备份至 <路径>」
|
|
34
|
+
|
|
35
|
+
升级本 skill 时,配置结构如有变化必须同步更新本节的当前版本号与迁移说明;禁止在未声明版本变更的情况下静默修改配置语义。
|
|
36
|
+
|
|
37
|
+
## 文档同步自检纪律(维护者必读)
|
|
38
|
+
|
|
39
|
+
修改本 skill 任一文件(SKILL.md / user-config.md / resources/*)后,必须 grep 全文核对相关关键词在各文件间一致(如章节名/字段名/效果参数改名时新旧词全仓核对,旧词零残留才算完成)。修改 HTML 效果必须同步更新 `resources/reference.html` 与 `disk-and-html.md` 对应描述,三者以 reference.html 为真相源;改完后互相 grep 关键参数确认对齐。
|
|
25
40
|
|
|
26
41
|
## 规则速览
|
|
27
42
|
|
|
28
|
-
-
|
|
29
|
-
-
|
|
43
|
+
- 任务进度 3-6 点、每点 20-40 字;序号用中文顿号(1、2、3)
|
|
44
|
+
- 三段兜底写「暂无」;计划点带进度百分比与预估用时+完成标准(口述有时必写);风险阻塞点四环(问题+影响+建议+责任与时间,第四环口述有时必写)
|
|
30
45
|
- 用时单位 XH(小时),估算值注明「约」
|
|
46
|
+
- 数字凡有对比基准必带;业务结果指标优先于提交统计;流水无主语、结论判断归因处允许「我」;落笔前五问自检(结论/基准/闭环/可验证/归属)
|
|
31
47
|
- 完整规则(聚合来源 / 纯文字模式 / 写作风格约束 / 使用提示)见 `resources/content-rules.md`
|
|
@@ -1,41 +1,43 @@
|
|
|
1
1
|
# 内容规则
|
|
2
2
|
|
|
3
3
|
## 输出内容与数据来源
|
|
4
|
-
-
|
|
5
|
-
- 任务点格式:1
|
|
6
|
-
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
4
|
+
- 三段结构:今日任务进度(3-6 点)/ 明日计划 / 风险阻塞点
|
|
5
|
+
- 任务点格式:1、任务描述(量化数据)- 进度XX% - 用时XH
|
|
6
|
+
- 量化数据优先级:用户口述的业务结果指标(响应时间/错误率/成功率/转化率等)优先写入;提交统计(文件数/行数/提交次数)仅在无业务指标时兜底;两者都有时业务指标在前、提交统计后置或省略
|
|
7
|
+
- 数字凡有对比基准必带(环比/同比/目标完成度至少其一,如「+18%」「达目标 90%」);无基准来源时不作要求
|
|
8
|
+
- 任务来源(默认):各仓库当日 提交记录自动聚合 + 本次会话中用户已提及/口述的工作内容 + 用户口头补充,全部合并去重;仅当用户明确说"只整理这段文字/只按这段"时才忽略提交记录与会话上下文、只用指定文字(见「纯文字整理模式」)
|
|
9
|
+
- 「明日计划」取材双通道:①用户口述/文字补充的计划(优先并入);②一次生成连续多天日报时(本次批量生成中后面日期的日报,或 reports 目录中已存在的后续日报),从后一天日报的「今日任务进度」中抽取任务作为当天「明日计划」(抽取数量灵活、不设死上限:后续完成任务多且连续性强时可多抽至 4-5 条,少则抽 1-2 条,与后续日报内容形成呼应即可),描述改写为计划语气(完成态改进行态:如「完成 XX 重构」→「推进 XX 重构」「继续 XX 开发」,去掉量化数据/进度/用时);批量多天时优先保证跨天连续性:抽取时尽量让当天「明日计划」与后一天「今日任务进度」形成「计划→完成」的同主题承接链(如 11.05 计划「推进底部导航重构」→ 11.06 完成「完成底部导航重构」,同一条工作线前后呼应,跨天任务尽量串成连续的工作链);批量中最后一天无后续日报时,该段按口述或「暂无」处理
|
|
10
|
+
- 量化数据取自 git --stat(文件数、增删行数);用时为合理估算(提交记录不记录耗时,估算值注明"约",可口头修正)
|
|
9
11
|
- 数据收集范围(按当前系统自动选择,另一系统的仓库自动跳过):macOS = NearCast / nearcast-server / nearcast-go / nearcast-admin / SmartCanteenConsumerMachineApp / TrustPay 共 6 个仓库;Windows = srf-app / srf-manage / srf-operation / srf-service / srf-web-user / srf-web-operation / srf-web-wx / srf-web-h5-teacher / srf-web-uop / Spec-Core-Smart-Canteen 共 10 个仓库;无当日提交的仓库不写入
|
|
10
|
-
- HTML 版为参考图式深蓝面板卡片美化样式(实心深蓝卡片 + 细密水平条纹 + 上下边缘高光线 + 左缘节色条,保留 ask 同款发光动效):顶部「一键复制」按钮(复制纯文本版)+ TL;DR
|
|
12
|
+
- HTML 版为参考图式深蓝面板卡片美化样式(实心深蓝卡片 + 细密水平条纹 + 上下边缘高光线 + 左缘节色条,保留 ask 同款发光动效):顶部「一键复制」按钮(复制纯文本版)+ TL;DR 摘要行、「今日任务进度」标题右侧带目标日期徽章 + 任务进度节内当日节奏条(上午/下午/晚上时段条,hover 显示时段提交明细)+ 节奏条下量化指标行(提交次数/涉及文件数/代码行数)+ 进度条终点圆点与流星扫描填充 + 液态玻璃卡片(@supports 兜底)+ CRT 扫描光带 + 全页 3D 微倾斜(±0.75°)、页脚署名 GENERATED BY SPECCORE TEAM(日期动态跟随目标日期),并随 FORMATS 默认落一张内容区截图 content-png(卡片整体 + 四周留白 + 日期徽章)
|
|
11
13
|
|
|
12
14
|
## 用户补充任务
|
|
13
15
|
|
|
14
16
|
用户调用时可能口头追加任务(如"再补充一下:上午改了角标接口,下午跟测试联调了"),按以下规则处理:
|
|
15
17
|
|
|
16
|
-
- **触发**:话术含"补充/加上/还有/另外/以及/对了"等追加词,或直接口述任务内容(说"
|
|
17
|
-
- **分段**:补充内容带分段词时按段并入——"明日计划/计划:xxx"→ 明日计划段;"风险/阻塞:xxx"→ 风险阻塞点段(说"风险暂无/无风险"→ 风险段写「暂无」);不带分段词默认并入"
|
|
18
|
+
- **触发**:话术含"补充/加上/还有/另外/以及/对了"等追加词,或直接口述任务内容(说"整理成日报/只整理这段文字/只按这段/不要别的来源"时走「纯文字整理模式」,不是追加)
|
|
19
|
+
- **分段**:补充内容带分段词时按段并入——"明日计划/计划:xxx"→ 明日计划段;"风险/阻塞:xxx"→ 风险阻塞点段(说"风险暂无/无风险"→ 风险段写「暂无」);不带分段词默认并入"今日任务进度"
|
|
18
20
|
- **拆条**:按语义主题拆分,一个主题一条;拆分信号:时间词(上午/下午/晚上)、追加连接词、分号顿号列举、数字列举(1、2、3)
|
|
19
|
-
- **润色**:口语整理为规范任务描述(动词开头、说清对象与结果);用户未给量化数据时,优先从
|
|
20
|
-
- **去重**:与
|
|
21
|
-
- **格式**:与
|
|
21
|
+
- **润色**:口语整理为规范任务描述(动词开头、说清对象与结果);用户未给量化数据时,优先从 提交记录补文件数/行数,无记录则省略量化、只写进度与用时(估算值注明"约")
|
|
22
|
+
- **去重**:与 提交记录聚合任务合并时,同一件事只保留一条
|
|
23
|
+
- **格式**:与 提交记录聚合条目同格式,接在"今日任务进度"下继续编号
|
|
22
24
|
|
|
23
|
-
## 纯文字整理模式(用户贴一段文字,无
|
|
25
|
+
## 纯文字整理模式(用户贴一段文字,无 提交记录)
|
|
24
26
|
|
|
25
|
-
用户调用时直接贴一段文字并说"整理成日报/根据这段生成日报"(可能不是开发岗位,没有任何
|
|
27
|
+
用户调用时直接贴一段文字并说"整理成日报/根据这段生成日报"(可能不是开发岗位,没有任何 提交记录),按以下规则处理:
|
|
26
28
|
|
|
27
|
-
- **触发**:话术含"整理/根据这段/以下内容/帮我梳理"等 + 附了一段多句文字/图片/文件,或明说"
|
|
28
|
-
- **数据来源**:用户文字/图片/文件为主源,**跳过
|
|
29
|
+
- **触发**:话术含"整理/根据这段/以下内容/帮我梳理"等 + 附了一段多句文字/图片/文件,或明说"只整理这段文字/只按这段/不要别的来源/不要别的来源"(与"写日报 + 补充一下"的区别:文字/图片/文件是唯一主源、跳过提交记录与会话上下文,不是追加)
|
|
30
|
+
- **数据来源**:用户文字/图片/文件为主源,**跳过 提交记录收集**(不跑聚合命令)且忽略本次会话其它工作内容;图片用 Read 视觉理解提取图中文字信息,md/txt 直接读文本,docx/pdf 优先尝试 pandoc 转文本(无 pandoc 则请用户粘贴文字);用户是开发且内容提到代码相关工作时,可仍收集提交记录用于补量化数据
|
|
29
31
|
- **三段归类**(用户文字没按段写明时用信号词归类):
|
|
30
32
|
- 含"明天/明日/接下来/计划/准备/打算/将要/待办" → 明日计划
|
|
31
33
|
- 含"风险/阻塞/问题/卡住/困难/待定/依赖/遗留" → 风险阻塞点
|
|
32
|
-
- 其余 →
|
|
34
|
+
- 其余 → 今日任务进度;全段无任何信号词 → 全部归入今日任务进度
|
|
33
35
|
- 用户已明确分段("今日完成:A;明日计划:B;风险:C")→ 按用户分段,不猜
|
|
34
36
|
- **拆条**:按语义主题拆分,一个主题一条;拆分信号:时间词(上午/下午/晚上)、连接词(还有/另外/以及)、分号顿号列举、数字列举(1、2、3)、换行/段落边界
|
|
35
37
|
- **润色**:口语整理为规范任务描述(动词开头、说清对象与结果),每点 20-40 字
|
|
36
|
-
- **量化数据**:无
|
|
38
|
+
- **量化数据**:无 提交记录 → 不写文件数/行数/提交次数;格式退化为「1、任务描述 - 进度XX% - 用时XH」
|
|
37
39
|
- **进度与用时**:文字没给进度时,完成任务默认 100%、计划默认 0%;用时/预估用时仅在用户文字给出时才写,没给就省略(不瞎编估算值)
|
|
38
|
-
-
|
|
40
|
+
- **风险阻塞点**:素材没给影响/建议时只列描述;素材含影响/建议/责任时间时按四环结构写全
|
|
39
41
|
- **日期/落盘/HTML**:与常规流程一致(默认今天、md/txt/html 三文件 + 内容区截图落盘、html 自动打开)
|
|
40
42
|
|
|
41
43
|
## 输出格式
|
|
@@ -45,37 +47,39 @@
|
|
|
45
47
|
|
|
46
48
|
> 生成时间:YYYY-MM-DD HH:MM:SS
|
|
47
49
|
|
|
48
|
-
##
|
|
50
|
+
## 今日任务进度
|
|
49
51
|
1、任务描述(量化数据:文件数/行数/提交次数)- 进度XX% - 用时XH
|
|
50
52
|
|
|
51
53
|
## 明日计划
|
|
52
|
-
1、任务描述 - 进度XX% - 预估用时XH
|
|
54
|
+
1、任务描述 - 完成标准:XX(时间点)- 进度XX% - 预估用时XH
|
|
53
55
|
|
|
54
56
|
## 风险阻塞点
|
|
55
|
-
-
|
|
57
|
+
- 问题描述;影响:xxx;建议:xxx;责任与时间:xxx(谁/何时,口述有时必写)
|
|
56
58
|
```
|
|
57
59
|
|
|
58
60
|
## 规则
|
|
59
61
|
|
|
60
|
-
-
|
|
62
|
+
- 任务进度 3-6 点,每点 20-40 字;序号用中文顿号(1、2、)
|
|
61
63
|
- 聚合后任务数超上限(6 点)时,同类小任务合并压缩到上限内;用户说「精简点/太长了」→ 条目数取下限、每点压缩到 20 字左右;说「详细点」→ 条目数取上限、每点写足 40 字
|
|
62
|
-
-
|
|
63
|
-
-
|
|
64
|
-
-
|
|
64
|
+
- 三段兜底:任务进度默认 100%;任务进度/明日计划/风险阻塞点无任何内容时该段写「暂无」(默认聚合时明日计划无 提交来源,用户没给计划就写「暂无」)
|
|
65
|
+
- 计划每点带进度百分比与预估用时;用户口述/文字给出完成标准时(如「周五前出唤醒效率对比」),必写「完成标准:XX(时间点)」,未给出则省略
|
|
66
|
+
- 风险阻塞点四环结构:问题+影响+建议+责任与时间,不写进度用时;第四环「责任与时间(谁/何时)」取自用户口述,未提供时省略
|
|
65
67
|
- 用时单位:XH(小时),估算值注明"约"
|
|
66
|
-
- 文字风格约束:①明日计划用计划态陈述句,动词取「推进/启动/开展/跟进/梳理/筹备/验证/排查/联调」等计划态词,禁用完成态词(完成/搞定/已实现/做完),可带「计划/预计/拟」字样(不必每条都有),句式「动词+对象+目标范围」(如「推进底部导航重构,完成主流程交互调整」),禁祈使句(「去做 xx」)与口语(「把 xx
|
|
68
|
+
- 文字风格约束:①明日计划用计划态陈述句,动词取「推进/启动/开展/跟进/梳理/筹备/验证/排查/联调」等计划态词,禁用完成态词(完成/搞定/已实现/做完),可带「计划/预计/拟」字样(不必每条都有),句式「动词+对象+目标范围」(如「推进底部导航重构,完成主流程交互调整」),禁祈使句(「去做 xx」)与口语(「把 xx 弄一下/搞搞」);②完成任务用动词开头的完成态陈述句(完成/修复/优化/重构/开发/实现/接入/升级/排查/联调/上线),说清对象与结果(如「完成底部导航重构」);③风险阻塞点四环结构:问题+影响+建议+责任与时间(问题客观陈述、影响说明后果、建议给出可执行对策、责任与时间来自口述缺省省略),不写抱怨与情绪话;④任务流水与清单条目保持无主语(动词开头);结论、判断、归因处允许第一人称「我」(「我主导了 XX 联调」「我判断风险可控」「我推动 XX 落地」),团队协作成果用「我们」;不用口语语气词(啦/啊/吧/哈/哦/呢)、不用 emoji、不用口语形容词(差不多/还行/基本上/搞不定/一堆);用户口述/补充的口语内容一律先润色为规范书面语再写入(「上午改了角标接口」→「完成角标接口改造」),量化数据(文件数/行数/进度/用时)格式不变
|
|
69
|
+
- 技术动作翻译:用户口述技术动作且带结果数据时,翻译为业务结果表述(「重写 SQL 加索引」→「查询响应 3.2s→0.4s」);仅含动作无结果时保留动作描述,并在对话中提示可补充结果指标
|
|
70
|
+
- 落笔前五问自检:①第一句是不是结论?②数字有没有对比基准?③卡点有没有责任动作和时间?④计划能不能被验证?⑤个人贡献与团队成果的归属是否清晰?任一不过,改写后再输出
|
|
67
71
|
- 报告标题下输出生成时间,精确到时分秒(YYYY-MM-DD HH:MM:SS)
|
|
68
72
|
- 生成报告时,对话中先输出简要「使用提示」(几条速览 + 完整说明引用)再输出报告正文,固定条目:
|
|
69
73
|
- 默认生成今天;「昨天的日报 / 上周三的日报 / 10月20号的日报」指定日期
|
|
70
74
|
- 「补充一下:xxx」追加任务(「明日计划:/风险:」分段词自动归段);贴文字/发图片/给文件「整理成日报」默认直接生成,说「先看看效果」→ 确认后再落盘
|
|
71
|
-
-
|
|
75
|
+
- 默认多源聚合:提交记录(有仓库时)+ 本次会话已提的工作内容,没有提交记录则以口述/文字为准;说「只整理这段文字」→ 仅用该文字
|
|
72
76
|
- 「写到桌面 / 不落盘 / 只要 md / 只要截图 / 这次不截图 / 别开浏览器 / 保留之前的」临时控制落盘;「这次按 xxx 模板来」临时换模板
|
|
73
77
|
- 生成完成后在对话中告知本次落盘的文件完整路径清单(目录 + 各文件名,Windows 用反斜杠)
|
|
74
78
|
- 默认配置长期生效:改 skill 文件顶部「默认配置」节(DISK/FORMATS/DIR/OPEN_HTML/TEMPLATE/CONFIRM)
|
|
75
79
|
- 📖 完整使用说明:问「日报怎么用」
|
|
76
|
-
-
|
|
77
|
-
- 目录名 = 目标日期(解析出的报告日期),不是生成时刻:整理"昨天的日报"
|
|
78
|
-
- 纯文字整理模式:用户贴一段文字/发图片/给文件说"整理成日报/只按这段"时跳过
|
|
80
|
+
- 默认聚合来源:提交记录(有仓库时)+ 本次会话中用户已提及/口述的工作内容全部合并去重(没有提交记录 或非代码工作以口述/文字为主);仅当用户明确说"只整理这段文字/只按这段"时,才只用指定文字、忽略其它来源
|
|
81
|
+
- 目录名 = 目标日期(解析出的报告日期),不是生成时刻:整理"昨天的日报"时目录用昨天日期、提交记录收集范围也是昨天;标题中的 YYYYMMDD 同为该目标日期
|
|
82
|
+
- 纯文字整理模式:用户贴一段文字/发图片/给文件说"整理成日报/只按这段"时跳过 提交记录收集与会话上下文,内容为主源(图片 Read 视觉提取、md/txt 直接读、docx/pdf 优先 pandoc 转文本);按信号词自动三段归类(用户已分段则按用户分段);无量化数据不写文件数/行数,进度默认完成 100%/计划 0%,用时用户没给就省略;CONFIRM: never 默认直接生成落盘不确认,CONFIRM: text/always 或用户说"先看看效果"时先出整理效果、用户说"可以/确认/落盘"后再落盘,说"改一下 xxx"按意见修改后重新确认,说"不用确认/直接落盘"跳过确认(CONFIRM 配置控制,临时口头要求优先)
|
|
79
83
|
- 模板优先级:用户临时口头指定的模板 > 顶部 TEMPLATE 配置(custom 用「📝 自定义模板」节结构,default 用内置三段式);自定义模板只改段名/段数/条目格式,其余规范(中文顿号序号、生成时间、落盘、HTML 样式)不变
|
|
80
84
|
- 日期优先按自然语言解析(如"昨天的日报"、"上周三的日报");显式参数 `/daily-report [YYYYMMDD] [md|txt|html]` 等价于自然语言,日期缺省为今天
|
|
81
85
|
- 跨系统兼容:执行时先检测当前系统(macOS/Windows),所有路径、命令、浏览器均按系统分支取值(DIR auto→DIR_MAC/DIR_WIN、仓库表对应路径列、Chrome/Edge 路径、open/Start-Process、桌面/回退目录);禁止假设单一系统
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
| srf-web-uop | - | d:\Web_Projects\srf-web-uop |
|
|
22
22
|
| Spec-Core-Smart-Canteen | - | d:\Workspace_QCoder\Spec-Core-Smart-Canteen |
|
|
23
23
|
|
|
24
|
-
- 「-」= 该仓库在当前系统不存在,跳过;当前系统对应列全为「-」(陌生机器)时跳过
|
|
24
|
+
- 「-」= 该仓库在当前系统不存在,跳过;当前系统对应列全为「-」(陌生机器)时跳过 提交记录收集,只按会话/文字内容生成
|
|
25
25
|
|
|
26
26
|
命令模板:
|
|
27
27
|
|
|
@@ -32,9 +32,9 @@ git -C <仓库路径> log --since="YYYY-MM-DD 00:00:00" --until="YYYY-MM-DD 23:5
|
|
|
32
32
|
- 汇总每个提交涉及的**文件数**与**增删行数**(来自 --stat),作为量化数据
|
|
33
33
|
- **行数统计口径(防生成物噪音)**:统计增删行数前必须先剔除生成物路径(如 `.speccore/code-graph/` 下的 graph.json:单文件可能贡献数十万行,会撑爆指标);numstat 输出为 `add\tdel\tpath` 三列,用 `grep -vE $'\t\.speccore/code-graph/'` 按制表符+路径过滤(正则匹配行首无效);统计后若行数仍异常巨大(>5 万行),用 `sort -rn | head -8` 定位元凶文件再排除;日报指标卡(提交次数/涉及文件数/代码行数)与 HTML 量化指标行均用过滤后口径
|
|
34
34
|
- 同主题多提交(含多次提交与 MR 合并记录)合并为一条任务点,量化数据累加
|
|
35
|
-
-
|
|
35
|
+
- 提交记录无法给出实际耗时,用时取合理估算值,允许用户事后修正
|
|
36
36
|
- 无当日提交的仓库不写入日报
|
|
37
|
-
-
|
|
37
|
+
- 仓库路径(当前系统列)不存在/非代码仓库时静默跳过该仓库(不报错、不写入)
|
|
38
38
|
- 用户说「只写 xxx 的日报 / 只聚合 xxx 仓库」时只收集指定仓库
|
|
39
|
-
-
|
|
40
|
-
- 用户明确说"只整理这段文字/只按这段"
|
|
39
|
+
- 提交记录之外的默认来源:本次会话中用户已提及/口述的工作内容(任务、进度、风险等对话信息)一并聚合,与 提交记录去重合并
|
|
40
|
+
- 用户明确说"只整理这段文字/只按这段"时,忽略提交记录与会话上下文,只用指定文字
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
| 20261020 / 2026-10-20 | 直接使用 |
|
|
15
15
|
| 10月20号到10月25号的日报 / 11.05~11.07 / 上周一到上周五 / 10月20号到今天 | 连续日期批量生成:两端分别按本表单点规则解析(终点缺年份沿用起点年份、终点月份早于起点月份视为下一年,如「12月28号到1月3号」;终点可写「今天/昨天」),按日期正序逐日生成一份日报 |
|
|
16
16
|
|
|
17
|
-
-
|
|
17
|
+
- 目标日期写入日报标题与提交记录聚合的起止范围
|
|
18
18
|
- 批量生成流程:先一次性收集区间内所有日期的提交(逐日分片 --since/--until),再按日期正序逐日生成(每日可引用后一天数据做「明日计划」,见「输出内容与数据来源」节),最后统一落盘与截图;批量时只自动打开最后一天(最新一天)的 html、其余仅落盘不开浏览器,避免开多个标签页;对话中按日期分隔输出各天 md 正文
|
|
19
19
|
- 落盘子目录名永远用解析出的目标日期("昨天的日报"→ 昨天日期),与生成当天/生成时刻无关,不因跨零点而改变
|
|
20
20
|
- 未提及任何日期词(如"今天/昨天/10月20号")时,一律默认今天直接生成,不追问用户
|