skill-forge-hub 1.0.3 → 1.0.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/CHANGELOG.md CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  SkillForge(技能锻造坊)npm 包 `skill-forge-hub`(命令名 `skill-forge`)版本变更记录。
4
4
 
5
+ ## 1.0.4(2026-11-11)
6
+
7
+ **图表 echarts 化 + 数据源通用化 + 升级机制强化**
8
+
9
+ - 图表 echarts 化:周报/年报四类图表(月提交柱图/日提交柱图/环形图/热力图)改 CDN echarts 渲染(jsdelivr 5.5.1)——五主题联动换肤、shot 截图模式停动画、离线自动降级提示(.ech-off 提示文案);修复 weekly 概览 DOM 闭合层级(ov-bento 九子结构归位)与环中心文字溢出
10
+ - 数据源通用化:三报表新增 DATA_SOURCES 数据源清单(git 仓库聚合 / file 文件目录 / remote 远程源三类型示例,mac/win 双字段),默认模板不再出现真实机器地址(~/reports、%USERPROFILE%\reports 通用路径模板);CONFIG_VERSION 2→3;deck-stage/prompt-pouch 模板值同步通用化;全仓零真实地址残留
11
+ - 升级机制强化:①新增 .installed-manifest 安装清单——升级时只清理清单内官方已删除的文件与空目录,用户自建文件一律不动(旧版本安装无清单时跳过清理,升级后补写清单);②article-to-html 植入 .preserve 保护清单(design-system.md 永不覆盖,官方更新另存 .upstream 对照);③meta-forge 机制五——.preserve 清单条件植入规范 + 校验清单 4b 项
12
+ - 验证:升级机制三场景真机测试 12 项断言全过(旧版无清单升级 / 官方删文件精准清理 / 用户自建与定制文件保护)
13
+
5
14
  ## 1.0.3(2026-11-11)
6
15
 
7
16
  **窄屏分辨率适配 + 图表默认动画补齐**
package/README.md CHANGED
@@ -97,7 +97,7 @@ cp -R spec-doc2spec spec-spec2doc <你的 AI 助手技能目录>/
97
97
  2. 交互三选一:`[1] 官方覆盖`(旧配置在备份中随时找回)/ `[2] 保留我的` + 官方版另存 `.upstream` 对照(默认)/ `[3] 稍后处理`(本次不生成对照文件)
98
98
  3. `--yes` 或非交互环境默认 `[2]`,最安全
99
99
  - **版本一致**:无感升级,只更新技能文件,配置原样保留
100
- - **结构同步**:升级时清理官方已删除的文件与空目录(历史只增不删的废弃文件不再残留);`user-config.md`、`.preserve` 清单文件、`.upstream` 对照、`.bak-*` 备份与 `node_modules` 依赖永远不动
100
+ - **结构同步**:升级按 `.installed-manifest` 安装清单精准同步官方文件增删——只清理清单内官方已删除的文件与空目录,用户自建文件一律不动(旧版本安装无清单时跳过清理,升级后补写);`user-config.md`、`.preserve` 清单文件、`.upstream` 对照、`.bak-*` 备份与 `node_modules` 依赖永远不动
101
101
 
102
102
  技能维护者约定:官方配置结构每次变化(新增/改名/删除配置键)时,`user-config.md` 的 `CONFIG_VERSION` 递增 1,并在 SKILL.md「配置版本机制」节写明迁移规则(AI 每次执行前也会自检该版本)。
103
103
 
@@ -12,7 +12,7 @@ disable-model-invocation: false
12
12
  ## 生成流程
13
13
 
14
14
  0.5 **周期歧义分流**:用户说「写总结/工作总结/写个汇报/做一份总结」等未言明周期的词 → AskUserQuestion 三选一(日报/周报/年报)确认周期再继续,不擅自默认
15
- 0. **读用户配置**(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION、自定义模板)→ 先 Read 同目录 `user-config.md`
15
+ 0. **读用户配置**(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION/DATA_SOURCES、自定义模板)→ 先 Read 同目录 `user-config.md`
16
16
  1. **解析年度**(自然语言 → 目标年度区间)→ 读 `resources/date-parsing.md`
17
17
  2. **收集数据**(多源:会话口述 / 文字 / 文件 / 图片 / 代码提交记录,合并去重)→ 读 `resources/data-collection.md`
18
18
  3. **内容归类与润色**(五段式结构 / 聚合来源 / 纯文字模式 / 输出格式 / 写作风格)→ 读 `resources/content-rules.md`
@@ -22,13 +22,13 @@ disable-model-invocation: false
22
22
 
23
23
  ## ⚙️ 配置与自定义模板
24
24
 
25
- **执行本 skill 前必须先 Read 同目录 `user-config.md`**:默认配置(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION)与自定义模板都在该文件中,以它为准。升级技能时 user-config.md 不会被覆盖,你的修改永久保留;官方更新配置时另存 `user-config.md.upstream` 对照文件,可按需手动合并新配置点。
25
+ **执行本 skill 前必须先 Read 同目录 `user-config.md`**:默认配置(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION/DATA_SOURCES)与自定义模板都在该文件中,以它为准。升级技能时 user-config.md 不会被覆盖,你的修改永久保留;官方更新配置时另存 `user-config.md.upstream` 对照文件,可按需手动合并新配置点。
26
26
 
27
27
  - **THEME**:html 页面主题,tech 深蓝科技(默认)/ biz 浅色商务 / mono IDEA 黑亮 / light IDEA 白亮 / warm 温暖渐变;生成时写 `<html data-theme="THEME值">` 定默认,页面右下角换肤坞随点随换(localStorage 记忆、?shot 截图模式与打印隐藏)
28
28
 
29
29
  ## 配置版本机制(升级保护)
30
30
 
31
- 本 skill 当前配置版本为 `2`(对应 user-config.md 中的 `CONFIG_VERSION`)。执行时若发现 user-config.md 的 CONFIG_VERSION 与本节声明的当前版本不一致:
31
+ 本 skill 当前配置版本为 `3`(对应 user-config.md 中的 `CONFIG_VERSION`)。执行时若发现 user-config.md 的 CONFIG_VERSION 与本节声明的当前版本不一致:
32
32
 
33
33
  1. 先将旧 user-config.md 备份为 `user-config.md.bak-<时间戳>`(同目录,绝不删除旧值)
34
34
  2. 按本节「配置升级规则」迁移字段:新增字段补默认值、改名字段按映射改写、删除字段的值保留在备份中并在对话提示用户手动确认
@@ -39,7 +39,7 @@ disable-model-invocation: false
39
39
 
40
40
  **无法迁移项处理**(值域失效 / 语义漂移 / 数据不兼容):三情形——①旧值不在新值域(如旧模板/主题名已移除)②同名键含义变化(单位/枚举变更)③数据文件 schema 不兼容。三绝不:绝不静默(无法迁移项停下问,不猜值)、绝不丢失(旧值永远在 .bak-时间戳)、一次说清(升级报告三段式:⚠️ 版本与备份路径 → ✅ 已自动迁移清单 → 🟡 无法迁移项逐条附原因+影响+建议替代);随后 AskUserQuestion 三选项(A 用建议值 / B 用户给新值 / C 保持旧配置——不更新 CONFIG_VERSION,每次执行再提醒);报告必附回滚一句话;数据文件迁移前先复制 .bak-时间戳,能映射则映射、不能则写兼容层或留备份提示手动整理
41
41
 
42
- 当前版本变更记录:v1→v2 新增 THEME 字段(默认 tech;发现旧配置时按迁移规则补默认值)。
42
+ 当前版本变更记录:v1→v2 新增 THEME 字段(默认 tech;发现旧配置时按迁移规则补默认值)。v2→v3 新增 DATA_SOURCES 数据源清单段(默认空清单 + git/file/remote 三类型示例注释;DIR_MAC/DIR_WIN 默认值通用化——已配置用户保留原值不受影响)。
43
43
 
44
44
  ## 文档同步自检纪律(维护者必读)
45
45
 
@@ -4,18 +4,19 @@
4
4
 
5
5
  ## 1. 代码仓库全年提交聚合(可选,开发类用户)
6
6
 
7
- - 遍历仓库清单(见 disk-and-html.md 的仓库清单节),对每仓执行全年统计:
7
+ - 遍历 user-config.md 的 DATA_SOURCES 清单(type: git 项;个人数据源必须写在 user-config.md,本文件随升级覆盖),对每仓执行全年统计:
8
8
  - 总提交数:`git log --since={区间起} --until={区间止} --oneline | wc -l`
9
9
  - 增删行数:`git log --since=... --until=... --numstat --pretty=tformat: | awk` 汇总 add/del
10
10
  - **先剔除生成物路径**(.speccore/code-graph/、node_modules、dist、*.lock 等,用 grep -vE 按制表符+路径过滤),否则 graph.json 之类单文件可贡献数十万行噪音
11
11
  - 月度分布:`git log --since=... --until=... --format='%ad' --date=format:'%Y-%m' | sort | uniq -c`(12 个月柱图数据)
12
12
  - 里程碑:`git tag` / `git log --merges --oneline` 提取版本发布与重要合并,读 tag 信息取版本号与日期
13
- - 仓库按系统取有效路径(macOS / Windows 双列表,空列跳过)
13
+ - 仓库按系统取有效路径(mac / win 双字段,「-」= 该系统不存在跳过)
14
14
 
15
15
  ## 2. 会话口述与文字材料
16
16
 
17
17
  - 用户口述的年度大事(「年初做了 X」「Q3 上了 Y」)逐条记录
18
18
  - 用户提供的总结草稿/文档(md/txt/docx)Read 提取要点;图片逐张 Read 识别内容
19
+ - DATA_SOURCES 清单中 type: file 的文件/目录直接 Read 提取要点;type: remote 的 url 联网拉取内容提取要点(仅收集时联网,HTML 产物仍零外链)
19
20
  - 聊天记录/周报/日报文件也可作为素材
20
21
 
21
22
  ## 3. 合并去重与口径
@@ -1,4 +1,4 @@
1
- > ⛔ **Reference 铁律(最高优先)**:本目录 `reference.html` 是定稿样式源码。生成 HTML 时必须先 Read `resources/reference.html` 与本文件两份,以 reference.html 为骨架模板逐处替换数据(标题/日期/五段条目/TL;DR 摘要/数据卡数字/月提交柱图),本文件的描述是参数解释、变体规则与禁止项;两者冲突时**以 reference.html 为准**。修改本 skill 的 HTML 效果时,必须同步更新 `resources/reference.html` 与本文档的对应描述,禁止只改一处。
1
+ > ⛔ **Reference 铁律(最高优先)**:本目录 `reference.html` 是定稿样式源码。生成 HTML 时必须先 Read `resources/reference.html` 与本文件两份,以 reference.html 为骨架模板逐处替换数据(标题/日期/五段条目/TL;DR 摘要/数据卡数字/月提交柱图数据数组——IIFE 内 MONTHS/VALS),本文件的描述是参数解释、变体规则与禁止项;两者冲突时**以 reference.html 为准**。修改本 skill 的 HTML 效果时,必须同步更新 `resources/reference.html` 与本文档的对应描述,禁止只改一处。
2
2
 
3
3
  # 落盘与 HTML(年度版式)
4
4
 
@@ -11,16 +11,16 @@
11
11
 
12
12
  ## HTML 年度版式(深蓝面板体系,与日报/周报同源)
13
13
 
14
- - 复用日报/周报深蓝面板视觉体系:背景 #0a1929 + SVG feTurbulence 微噪点(opacity .04)+ 三层科技底纹(.grid-pattern 60px 青色细网格 var(--scan-dim) + .stars 8 个 1-1.5px 星点白/青/紫/绿散落 + .scanlines 2px 周期扫描线 var(--scan-dim));禁用任何 CDN 与外部网络引用(@import、外链 CSS/JS/图片/网络字体一律禁止,页面必须公司内网离线双击可打开、零外部依赖);字体全用系统本地字体栈 ui-monospace/'SF Mono'/SFMono-Regular/Menlo/Consolas;颜色全部用 CSS 变量统一主题令牌:19 令牌 × 5 主题(tech 深蓝科技(默认,色值与旧 ask 色板一致)/biz 浅色商务/mono IDEA 黑亮(JetBrains New UI Dark 官方色系:编辑区 #1e1f22 + 面板 #2b2d30)/light IDEA 白亮(IntelliJ Light 官方色系:白编辑区 + 浅灰面板)/warm 温暖渐变,html[data-theme] 运行时切换;12 核心契约 --bg/--bg2/--panel/--panel-solid/--text/--muted/--accent/--accent2/--border/--glow/--title-grad/--tag-bg + 报告扩展 --glow-soft/--scan/--scan-dim/--heat/--green/--orange/--rose;生成时按 THEME 配置写 data-theme 定默认,页面右下角换肤坞五色点随点随换、localStorage 记忆、?shot 截图模式与打印隐藏)
14
+ - 复用日报/周报深蓝面板视觉体系:背景 #0a1929 + SVG feTurbulence 微噪点(opacity .04)+ 三层科技底纹(.grid-pattern 60px 青色细网格 var(--scan-dim) + .stars 8 个 1-1.5px 星点白/青/紫/绿散落 + .scanlines 2px 周期扫描线 var(--scan-dim));图表渲染用 echarts@5.5.1(body 末尾主 script 之前引入 `<script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>`,页面唯一网络引用;离线/内网无外网加载失败时图表容器显示 data-off 降级提示文字、页面其余内容正常浏览不受影响);除 echarts 外禁用任何 CDN 与外部网络引用(@import、外链 CSS/图片/网络字体一律禁止);字体全用系统本地字体栈 ui-monospace/'SF Mono'/SFMono-Regular/Menlo/Consolas;颜色全部用 CSS 变量统一主题令牌:19 令牌 × 5 主题(tech 深蓝科技(默认,色值与旧 ask 色板一致)/biz 浅色商务/mono IDEA 黑亮(JetBrains New UI Dark 官方色系:编辑区 #1e1f22 + 面板 #2b2d30)/light IDEA 白亮(IntelliJ Light 官方色系:白编辑区 + 浅灰面板)/warm 温暖渐变,html[data-theme] 运行时切换;12 核心契约 --bg/--bg2/--panel/--panel-solid/--text/--muted/--accent/--accent2/--border/--glow/--title-grad/--tag-bg + 报告扩展 --glow-soft/--scan/--scan-dim/--heat/--green/--orange/--rose;生成时按 THEME 配置写 data-theme 定默认,页面右下角换肤坞五色点随点随换、localStorage 记忆、?shot 截图模式与打印隐藏)
15
15
  - 头部卡片:标题按行业词典「标题」变量取词 + 年份前缀(如「2026 研发年度总结」;话术含职业词 → 该词条标题,未提职业 → 按 ROLE 画像匹配词条,词典外行业 → 「YYYY 年度总结」兜底;词典标题行见 `resources/industry-dictionary.md`)+ 副标题(ROLE 画像或年度区间)+ 生成时间行;speccore ask 同款发光特效:四边 1px 青色浮光线 transparent→var(--accent)→transparent 整条平移扫动(上 scanX 左→右、右 scanY 上→下、下 scanX-rev 右→左、左 scanY-rev 下→上,四线同周期 3s linear 单向平移,亮段完整穿越卡片后消失于两端界外,卡片 overflow:hidden 裁剪;禁止自创 background-position 滚动/常驻辉光/往返摆动/亮段半嵌常驻变体)+ 顶部光斑 cardGlow(radial-gradient ellipse at 50% 10% var(--glow)→transparent 70%,opacity .5→1 + scale 1→1.6,transform-origin top center,3s 循环,头部与每张分节卡片内均放 .card-glow 层)+ 标题文字青色光晕呼吸(text-shadow 双圈 3s 循环)
16
16
  - 五张分节卡片(实心深蓝底 #0b1e37 + 1px 白色微透细线 8px 周期淡条纹(repeating-linear-gradient(180deg, rgba(255,255,255,.012) 0 1px, transparent 1px 8px),与日报/周报同款,头部卡片同条纹) + 上下边缘 1px 微亮描边 #0f3350 + 圆角 6px + overflow:hidden + 保留阴影与 inset 内发光),左侧 8px 宽节色竖线贯穿整卡(box-shadow 0 0 12px 同色 30% 光晕),内容 padding-left 24px;节色:概览亮蓝 linear-gradient(180deg,#38bdf8,#0ea5e9) / 成果青绿 linear-gradient(180deg,#5eead4,#14b8a6) / 成长紫 linear-gradient(180deg,#a5b4fc,#6366f1) / 反思玫红 linear-gradient(180deg,#fda4af,#e11d48) / 展望橙 linear-gradient(180deg,#fdba74,#f97316);节标题 18px 同色渐变 SVG 语义图标(概览=仪表盘、成果=奖杯、成长=上升箭头、反思=三角警示、展望=日历)+ 文字微光晕(h2 flex gap 10px,标题色=节色亮端,同色双圈发光字 3s 呼吸 secGlow 动画,仅节标题文字发光,SVG 图标不加)
17
17
  - 数字选择:用户口述的业务结果指标(响应时间/错误率/转化率/成功率等)优先写入,提交统计(提交数/文件数/行数)仅在无业务指标时兜底,两者都有时业务指标在前、提交统计后置或省略;数字凡有对比基准必带(环比/同比/目标完成度至少其一,如「+18%」「达目标 90%」),无基准来源时不作要求 - 概览节:一句话 TL;DR 引言行 + 核心数据卡 3-6 张横排(.stat-card flex 均分:大数字 28px 渐变字 + 12px muted 标签 + 11.5px 同比小字「较去年:+18%」,上涨 --green 绿、下跌 --rose 红;数据卡左侧小色条同概览节色)
18
18
  - 里程碑节:纵向时间线(.timeline 左侧 2px 青色竖线 + 季度节点:Q1/Q2/Q3/Q4 圆形节点(节色渐变球 + 光晕,当前季度节点加呼吸动画)+ 右侧内容(成果描述 15px + 量化小字 12px 青灰 + 季度徽章 11px muted 胶囊);季度内多条共用季度节点,条目间青色虚线分隔)
19
19
  - 成长节/反思节:条目沿用 3D 立体圆球序号徽章(28px 白字,径向渐变球面(受光点 circle at 30% 28%,浅亮→主色→深色)+ inset 右下内暗影 + ::before 左上椭圆高光点 + 底部投影与同色光晕;成长紫、反思玫红);反思条三环展开:问题主行 + 影响行 12px 青灰「影响:xxx」+ 改进行 12px 青色「改进:」加粗前缀
20
20
  - 展望节:目标条目卡(目标描述 15px + 量化指标加粗 + 分季度行动节点小胶囊 11px(Q1 起…/Q2 完成…,muted 字 + 青色细边 var(--border) + 淡青底))
21
- - 年度提交月度柱图(研发词条;其它词条按职业词典图表主题):.cb-col 12 根柱一月到十二月、.cb-bar width:24px 柱宽(太小显细弱)、柱高按当月提交数、position:relative 柱上带 .cb-tip hover 浮层「X月 · N 次提交」;置于里程碑节内时间线之后
21
+ - 年度提交月度柱图(研发词条;其它词条按职业词典图表主题):.cb-wrap 内 .ech echarts bar 容器 110px 高(#monthChart)、12 根柱一月到十二月、柱高按当月提交数、tooltip 显示「X月 · N 次提交」、--accent2→--accent 渐变柱身 + glow 光晕;置于里程碑节内时间线之后
22
22
  - 内容区 .wrap width:clamp(640px, 60%, 1200px)(与日报/周报同款自适应宽度,宽屏占 60% 不留大空边)+ 上下 padding 40px、左右 0 - 头部卡片内生成时间徽章下居中青色渐变 40px 大胶囊「一键复制」按钮(var(--accent)→var(--accent2),30px 青色光晕,hover 45px 光晕上浮;flex 居中布局,内置 16px 内联 SVG 双矩形复制图标(白色 currentColor 描边、图标与文字 gap 8px、禁用 emoji 图标),复制成功后图标切对勾、文字变「已复制」);复制源必须用 txt 文件内容(含换行、无 #/##/> 等 Markdown 符号,严禁用 md 内容当复制源);JS 用 navigator.clipboard.writeText,失败回退隐藏 textarea + document.execCommand('copy')(兼容 file:// 打开)
23
- - 入场动画:头部淡入下滑、五张卡片依次错峰上浮淡入(概览 0.13s/成果 0.26s/成长 0.4s/反思 0.54s/展望 0.68s);滚动入场:初始视口外的卡片滚到视口才上浮渐显(html.js 门控 + IntersectionObserver,translate 独立属性不碰 transform——hover 3D 偏转零冲突,stagger 70ms 封顶 280ms、入场完即清 delay 不拖慢 hover 偏转,2s 兜底强制显示;无 JS/打印/截图模式一律全显);窄屏收敛:<680px 视口 wrap 满宽流式、边距收窄、h1 统一 26px(clamp 640px 下限在窄窗不再横向溢出);月提交柱图加载生长动画 cbGrow 1s(对齐周报柱图);月提交柱图 12 列窄屏随 flex 收缩(bar 弹性宽、gap 收窄),tip 浮层首末列锚定防裁剪、按钮弹入;卡片入场动画 fadeDown/fadeUp/riseIn 的 fill-mode 必须用 backwards 严禁 both(both 使动画结束后最后一帧 transform:none 永久覆盖 hover 的 3D 偏转 transform,hover 偏转会完全失效)
23
+ - 入场动画:头部淡入下滑、五张卡片依次错峰上浮淡入(概览 0.13s/成果 0.26s/成长 0.4s/反思 0.54s/展望 0.68s);滚动入场:初始视口外的卡片滚到视口才上浮渐显(html.js 门控 + IntersectionObserver,translate 独立属性不碰 transform——hover 3D 偏转零冲突,stagger 70ms 封顶 280ms、入场完即清 delay 不拖慢 hover 偏转,2s 兜底强制显示;无 JS/打印/截图模式一律全显);窄屏收敛:<680px 视口 wrap 满宽流式、边距收窄、h1 统一 26px(clamp 640px 下限在窄窗不再横向溢出);月提交柱图 echarts 默认生长动画(对齐周报柱图);?shot 截图模式 animation:false 直接渲染终态(headless 虚拟时间下动画帧不推进会停在初始帧导致截图空白);echarts 容器 width:100% 窄屏自适应无需特化、按钮弹入;卡片入场动画 fadeDown/fadeUp/riseIn 的 fill-mode 必须用 backwards 严禁 both(both 使动画结束后最后一帧 transform:none 永久覆盖 hover 的 3D 偏转 transform,hover 偏转会完全失效)
24
24
  - hover 微交互:卡片上浮 translateY(-2px) + 阴影加深 + inset 发光增强、条目淡青底 var(--tag-bg)、时间线节点与序号徽章放大微旋(li:hover .idx transform:scale(1.18) rotate(-4deg)、球内数字放大 12→14px、数字必须用 <b> 包裹(.idx b{display:inline-block;transition:transform .2s ease})+ li:hover .idx b{transform:rotate(-6deg)} 数字在球内独立微旋;用户澄清 hover 变大的字体仅小球内数字,desc 正文保持 15px 不变不加斜体;销售 demo 版类名 .num:li:hover .num scale(1.22) rotate(-6deg)、数字 13→15px 同样 <b> 包裹 + rotate(-6deg))、数据卡上浮、按钮上浮/按压回缩
25
25
  - 卡片级 3D 微倾斜(严禁全页级 mousemove 倾斜):每张卡片 hover 时仅该卡片随鼠标偏转(perspective(900px) + rotateY(calc(var(--mx,0)*2.5deg)) rotateX(calc(var(--my,0)*-2.5deg)) ±1.25° 极轻微,与 hover 上浮合并写同一条 transform 严禁拆两条相互覆盖);JS 对每张卡片监听 mousemove 计算卡内相对位置((clientX-rect.left)/rect.width*2-1 归一化 -1~1)只更新该卡 --mx/--my,mouseleave 归零回正,transition transform .18s 平滑;移动端无 mousemove 保持 0 不倾斜
26
26
  - CRT 扫描光带(.scanband position:fixed、left:0/right:0、height:150px、linear-gradient(180deg,transparent,var(--scan-dim) 50%,transparent)、animation:scanMove 11s linear infinite(top -22%→112%)、pointer-events:none、z-index:998,置于 scanlines 之下一层)
@@ -162,17 +162,9 @@ body{
162
162
  /* 柱图 */
163
163
  .cb-wrap{margin-top:18px;padding-top:14px;border-top:1px dashed var(--border)}
164
164
  .cb-title{font-size:12px;color:var(--muted);margin-bottom:12px;letter-spacing:1px}
165
- .cb-chart{display:flex;align-items:flex-end;gap:8px;height:110px}
166
- .cb-col{flex:1;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;height:100%;position:relative}
167
- .cb-bar{width:24px;background:linear-gradient(180deg,#5eead4,#14b8a6);border-radius:3px 3px 0 0;
168
- box-shadow:0 0 10px rgba(45,212,191,.35);transition:height .3s ease;animation:cbGrow 1s ease-out both}
169
- .cb-col:hover .cb-bar{box-shadow:0 0 16px rgba(45,212,191,.6)}
170
- .cb-label{font-size:9px;color:var(--muted);margin-top:4px}
171
- .cb-tip{position:absolute;bottom:calc(100% + 6px);left:50%;transform:translateX(-50%) translateY(4px);
172
- background:var(--panel-solid);border:1px solid var(--glow);color:var(--text);font-size:10px;white-space:nowrap;
173
- padding:3px 8px;border-radius:4px;opacity:0;pointer-events:none;transition:opacity .18s,transform .18s;z-index:5}
174
- .cb-col:hover .cb-tip{opacity:1;transform:translateX(-50%) translateY(0)}
175
- @keyframes cbGrow{ from{height:0;} }
165
+ .ech{width:100%;height:110px}
166
+ .ech-off{display:flex;align-items:center;justify-content:center}
167
+ .ech-off::after{content:attr(data-off);font-size:11px;color:var(--muted);text-align:center;line-height:1.6;padding:0 10px}
176
168
  /* 序号徽章 3D 球 */
177
169
  .idx{flex:0 0 auto;width:28px;height:28px;border-radius:50%;position:relative;
178
170
  display:flex;align-items:center;justify-content:center;color:#fff;
@@ -247,7 +239,7 @@ footer{text-align:center;font-size:10px;color:var(--muted);letter-spacing:1px;pa
247
239
  .theme-dock .th-dot[data-theme="mono"]{ background:#1e1f22; }
248
240
  .theme-dock .th-dot[data-theme="light"]{ background:#ffffff; }
249
241
  .theme-dock .th-dot[data-theme="warm"]{ background:#d97706; }
250
- @media print{ .theme-dock{ display:none; .cb-bar{ animation:none !important; } } .rv{ opacity:1 !important; translate:none !important; .cb-bar{ animation:none !important; } } .cb-bar{ animation:none !important; } }
242
+ @media print{ .theme-dock{ display:none; } .rv{ opacity:1 !important; translate:none !important; } }
251
243
  /* 滚动入场:html.js 门控(无 JS/打印全显);初始视口外的卡片滚到视口才上浮渐显;translate 独立属性不碰 transform,hover 3D 偏转零冲突 */
252
244
  html.js .rv{ opacity:0; translate:0 16px; transition:opacity .5s ease-out, translate .5s ease-out; }
253
245
  html.js .rv.in{ opacity:1; translate:0 0; }
@@ -257,15 +249,6 @@ html.js .rv.in{ opacity:1; translate:0 0; }
257
249
  .wrap{ width:100%; max-width:none; }
258
250
  .header-card{ padding:26px 18px 20px; }
259
251
  .header-card h1{ font-size:26px; }
260
- /* 月提交柱图窄屏收敛:12 列 flex 收缩 + bar 弹性宽 + tip 首末列锚定防裁剪 */
261
- .cb-chart{ gap:4px; }
262
- .cb-col{ min-width:0; }
263
- .cb-bar{ width:100%; max-width:24px; }
264
- .cb-label{ font-size:8px; }
265
- .cb-col:first-child .cb-tip{ left:0; transform:translateY(4px); }
266
- .cb-col:first-child:hover .cb-tip{ transform:translateY(0); }
267
- .cb-col:last-child .cb-tip{ left:auto; right:0; transform:translateY(4px); }
268
- .cb-col:last-child:hover .cb-tip{ transform:translateY(0); }
269
252
  }
270
253
  </style>
271
254
  </head>
@@ -348,20 +331,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
348
331
  </div>
349
332
  <div class="cb-wrap">
350
333
  <div class="cb-title">年度提交月度分布(次)</div>
351
- <div class="cb-chart">
352
- <div class="cb-col"><div class="cb-tip">1月 · 0 次提交</div><div class="cb-bar" style="height:2px"></div><div class="cb-label">1月</div></div>
353
- <div class="cb-col"><div class="cb-tip">2月 · 0 次提交</div><div class="cb-bar" style="height:2px"></div><div class="cb-label">2月</div></div>
354
- <div class="cb-col"><div class="cb-tip">3月 · 0 次提交</div><div class="cb-bar" style="height:2px"></div><div class="cb-label">3月</div></div>
355
- <div class="cb-col"><div class="cb-tip">4月 · 0 次提交</div><div class="cb-bar" style="height:2px"></div><div class="cb-label">4月</div></div>
356
- <div class="cb-col"><div class="cb-tip">5月 · 0 次提交</div><div class="cb-bar" style="height:2px"></div><div class="cb-label">5月</div></div>
357
- <div class="cb-col"><div class="cb-tip">6月 · 0 次提交</div><div class="cb-bar" style="height:2px"></div><div class="cb-label">6月</div></div>
358
- <div class="cb-col"><div class="cb-tip">7月 · 335 次提交</div><div class="cb-bar" style="height:32px"></div><div class="cb-label">7月</div></div>
359
- <div class="cb-col"><div class="cb-tip">8月 · 1154 次提交</div><div class="cb-bar" style="height:92px"></div><div class="cb-label">8月</div></div>
360
- <div class="cb-col"><div class="cb-tip">9月 · 328 次提交</div><div class="cb-bar" style="height:31px"></div><div class="cb-label">9月</div></div>
361
- <div class="cb-col"><div class="cb-tip">10月 · 54 次提交</div><div class="cb-bar" style="height:8px"></div><div class="cb-label">10月</div></div>
362
- <div class="cb-col"><div class="cb-tip">11月 · 18 次提交</div><div class="cb-bar" style="height:4px"></div><div class="cb-label">11月</div></div>
363
- <div class="cb-col"><div class="cb-tip">12月 · 0 次提交</div><div class="cb-bar" style="height:2px"></div><div class="cb-label">12月</div></div>
364
- </div>
334
+ <div class="ech" id="monthChart" data-off="图表需联网加载 echarts,离线环境不显示"></div>
365
335
  </div>
366
336
  </section>
367
337
 
@@ -419,6 +389,7 @@ html.js .rv.in{ opacity:1; translate:0 0; }
419
389
  <button class="th-dot" type="button" data-theme="warm" title="温暖渐变"></button>
420
390
  </div>
421
391
 
392
+ <script src="https://cdn.jsdelivr.net/npm/echarts@5.5.1/dist/echarts.min.js"></script>
422
393
  <script>
423
394
  // 复制源 = txt 纯文本全文
424
395
  var TXT = "2026 研发年度总结\n\n生成时间:2026-11-09 17:03:01\n\n年度概览\nTL;DR:立项即狂奔的一年:SpecCore 规范驱动开发平台 7 月从零立项,4 个月 1889 次提交、576 个版本发布、代码库净增 19 万行,完成从单机 CLI 到流水线平台的蜕变。\n1、总提交数:1889 次(07-05 ~ 11-05)\n2、版本发布:576 个(v5.13.0 → v8.3.399)\n3、净增代码:+19.0 万行(+32.9 万 / -13.9 万)\n4、月度峰值:1154 次提交(8 月)\n\n核心成果与里程碑\n1、7 月立项首发:SpecCore CLI 完整功能落地,v5.13.0 首版发布(335 次提交、+5.4 万行)- Q3\n2、8 月密集攻坚:知识资产四层覆盖架构(TOC 目录/自动注入/RAG 检索/阅读清单)成形,月内 1154 次提交、+16.4 万行、发布 200+ 版本 - Q3\n3、9 月流水线成形:run 端到端流水线与迭代体系建立,+7.6 万行、328 次提交 - Q3\n4、10 月发布节奏收敛:v8.3 系列起跑,月度发布收紧至约 30 个版本,+1.8 万行 - Q4\n5、11-03 v8.3.370 累积发布:GLOBAL 治乱、反推域隔离、文档生成器升格、澄清链修复 - Q4\n6、11-04 v8.3.388:E2E 全链路深度检查 11 项修复 + execute 意图语义硬化 - Q4\n7、11-04 v8.3.394:反推链接力协议补全、全局分析默认纯技术、QA 环接力协议(exit 10)- Q4\n8、11-05 v8.3.399(截至当前):用例核对闸开卷设闸——execute 收尾逐用例勾稽,未实现即入修复环 - Q4\n\n经验与成长\n1、沉淀了「四层知识资产架构」(TOC 目录/自动注入/RAG 检索/阅读清单),解决了 AI 对规范库看不见、记不住、找不回的三类可见性断层。\n2、掌握了 ask 引擎意图识别与 AI 接力协议([SPECCORE_EXEC]/[SPECCORE_PROMPT]/[SPECCORE_CONTINUE] 标记链),人机协作可从任意断点续跑。\n3、建立了「聚合发布」节奏:小步高频提交 + 里程碑聚合 tag,兼顾问题定位粒度与交付速度。\n4、积累了质量门禁体系经验:骨架完成度自检、用例核对闸、QA 三阶段验证环,质量兜底不再依赖人肉复查。\n\n不足与反思\n1、8 月节奏过载:单月 1154 次提交、8-08 单日 95 个版本。\n影响:文档与代码同步滞后,质量债累积。\n改进:明年收敛为双周聚合发布、月度版本 ≤20 个。\n2、生成物污染统计口径:code-graph 等生成物单文件数十万行噪音曾混入行数统计。\n影响:工作量指标失真,误导投入判断。\n改进:统计前强制剔除生成物路径白名单。\n3、发布颗粒度两端失衡:Q3 一日最多 95 个 tag,Q4 单次聚合最多 10 个版本。\n影响:问题定位粒度在过细与过粗之间摇摆。\n改进:固定批次大小,每批 ≤10 版本聚合。\n\n新年展望与规划\n1、发布节奏工程化:双周聚合发布落地,2027 年版本发布总量 ≤120 个(Q1 建立节奏、Q2 稳定运行)。\n2、测试覆盖率跃升:核心链路自动化覆盖 ≥80%,用例核对闸覆盖全部命令(Q1 铺 E2E、Q3 达标)。\n3、生成物与体量治理:启动耗时降 30%、生成物目录隔离入白名单(Q2 完成隔离、Q4 验收性能)。\n4、生态落地:spec-once/流水线在 ≥3 个真实项目落地并沉淀案例(Q2 试点、Q4 案例库发布)。";
@@ -468,6 +439,45 @@ if (location.search.indexOf('shot=content') > -1) {
468
439
  });
469
440
  }
470
441
 
442
+ // 月度提交柱图(echarts CDN 渲染;离线时容器降级提示;?shot 截图模式停动画——headless 虚拟时间下动画帧不推进会停在初始帧)
443
+ (function(){
444
+ var el = document.getElementById('monthChart');
445
+ if (!el) return;
446
+ if (typeof echarts === 'undefined'){ el.classList.add('ech-off'); return; }
447
+ var noAnim = location.search.indexOf('shot=') !== -1;
448
+ var chart = echarts.init(el);
449
+ var MONTHS = ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'];
450
+ var VALS = [0,0,0,0,0,0,335,1154,328,54,18,0];
451
+ function tokens(){
452
+ var s = getComputedStyle(document.documentElement);
453
+ return {
454
+ accent:s.getPropertyValue('--accent').trim(), accent2:s.getPropertyValue('--accent2').trim(),
455
+ muted:s.getPropertyValue('--muted').trim(), text:s.getPropertyValue('--text').trim(),
456
+ border:s.getPropertyValue('--border').trim(), glow:s.getPropertyValue('--glow').trim(),
457
+ panel:s.getPropertyValue('--panel-solid').trim()
458
+ };
459
+ }
460
+ function option(){
461
+ var t = tokens();
462
+ return {
463
+ animation: !noAnim,
464
+ grid:{ left:2, right:2, top:18, bottom:18 },
465
+ tooltip:{ trigger:'axis', backgroundColor:t.panel, borderColor:t.border,
466
+ textStyle:{ color:t.text, fontSize:11 },
467
+ formatter:function(p){ return p[0].name + ' · ' + p[0].value + ' 次提交'; } },
468
+ xAxis:{ type:'category', data:MONTHS, axisTick:{ show:false },
469
+ axisLine:{ lineStyle:{ color:t.border } }, axisLabel:{ color:t.muted, fontSize:9 } },
470
+ yAxis:{ type:'value', show:false, max:1200 },
471
+ series:[{ type:'bar', data:VALS, barWidth:'46%',
472
+ itemStyle:{ borderRadius:[3,3,0,0],
473
+ color:new echarts.graphic.LinearGradient(0,0,0,1,[{ offset:0, color:t.accent2 },{ offset:1, color:t.accent }]),
474
+ shadowBlur:10, shadowColor:t.glow } }]
475
+ };
476
+ }
477
+ chart.setOption(option());
478
+ window.__sfEchartsTheme = function(){ chart.setOption(option()); };
479
+ window.addEventListener('resize', function(){ chart.resize(); });
480
+ })();
471
481
  // 主题换肤:五套配色随点随换;记忆上次选择(localStorage,失败静默);?shot 截图模式隐藏坞
472
482
  (function(){
473
483
  var THEMES = ['tech','biz','mono','light','warm'];
@@ -476,7 +486,8 @@ if (location.search.indexOf('shot=content') > -1) {
476
486
  if (location.search.indexOf('shot=') !== -1){ dock.style.display = 'none'; }
477
487
  function apply(t){ document.documentElement.setAttribute('data-theme', t);
478
488
  dock.querySelectorAll('.th-dot').forEach(function(d){ d.classList.toggle('on', d.getAttribute('data-theme') === t); });
479
- try{ localStorage.setItem('sf-report-theme', t); }catch(e){} }
489
+ try{ localStorage.setItem('sf-report-theme', t); }catch(e){}
490
+ if (window.__sfEchartsTheme) window.__sfEchartsTheme(); }
480
491
  var cur = document.documentElement.getAttribute('data-theme');
481
492
  var saved = null; try{ saved = localStorage.getItem('sf-report-theme'); }catch(e){}
482
493
  if (saved && THEMES.indexOf(saved) !== -1 && saved !== cur){ apply(saved); }
@@ -45,7 +45,7 @@
45
45
  - 词典外行业走兜底:按骨架 + 你提供的素材现场生成词条;说「记住这个行业」→ 固化为新词条
46
46
 
47
47
  ## 控制落盘(临时要求,仅对当次生效)
48
- - 默认:对话输出 Markdown + md/txt/html 三文件 + 内容区截图 content-png 落盘到 DIR(auto 按系统选:macOS=/Users/luzhaosheng/MyWork/智慧食堂/reports、Windows=d:\Workspace_QCoder\reports,路径以 user-config.md 顶部「默认配置」为准)/annual-YYYY/ + html 自动打开(DIR 目录/盘符不存在时自动改用用户主目录下 reports:macOS=~/reports、Windows=%USERPROFILE%\reports)
48
+ - 默认:对话输出 Markdown + md/txt/html 三文件 + 内容区截图 content-png 落盘到 DIR(auto 按系统选:macOS=~/reports、Windows=%USERPROFILE%\reports,模板默认值,路径以 user-config.md 顶部「默认配置」为准)/annual-YYYY/ + html 自动打开(DIR 目录/盘符不存在时自动改用用户主目录下 reports:macOS=~/reports、Windows=%USERPROFILE%\reports)
49
49
  - 说「写到桌面」→ 本次落盘到桌面(macOS=~/Desktop、Windows=%USERPROFILE%\Desktop);说「存到 ~/report / D:\report」→ 本次用指定目录(均自动按年度建子目录)
50
50
  - 说「不落盘/别写文件」→ 本次只在对话输出,不写文件、不开浏览器
51
51
  - 说「只要 md」「只出 html」「只要内容区截图」→ 本次只落指定格式文件;说「这次不截图」→ 本次跳过截图(content-png = 五张分节卡片整体一张图,四周约 40px 留白,不含头部标题、复制按钮、页脚)
@@ -58,7 +58,7 @@
58
58
  |---|---|---|
59
59
  | DISK | 是否落盘写文件 | true(落盘,默认)/ false(默认只在对话输出) |
60
60
  | FORMATS | 落盘哪些格式(数组) | [md, txt, html, content-png](默认,含内容区截图)/ [md, html] / [md, txt, html](不截图);content-png = 五张分节卡片整体截图(四周约 40px 留白),不含头部标题/复制按钮/页脚 |
61
- | DIR | 落盘根目录 | auto(按当前系统自动选 DIR_MAC / DIR_WIN,默认);DIR_MAC = macOS 根目录(/Users/luzhaosheng/MyWork/智慧食堂/reports);DIR_WIN = Windows 根目录(d:\Workspace_QCoder\reports) |
61
+ | DIR | 落盘根目录 | auto(按当前系统自动选 DIR_MAC / DIR_WIN,默认);DIR_MAC = macOS 根目录(模板默认 ~/reports,可改);DIR_WIN = Windows 根目录(模板默认 %USERPROFILE%\reports,可改) |
62
62
  | OPEN_HTML | 落盘后是否自动打开 html | true(自动打开,默认)/ false(不打开) |
63
63
  | TEMPLATE | 报告模板 | default(内置五段式,默认)/ custom(按「📝 自定义模板」节的结构生成) |
64
64
  | ROLE | 默认职业角色画像 | 全栈开发工程师(企业内技术开发)等;职业名 + 括号内工作内容 |
@@ -10,16 +10,28 @@
10
10
 
11
11
  ```yaml
12
12
  DISK: true # 是否落盘写文件;false = 默认只在对话输出,不写文件不开浏览器
13
- CONFIG_VERSION: 2 # 配置结构版本:skill 升级时若配置结构变化会递增;AI 每次执行前对比 SKILL.md「配置版本机制」节声明的当前版本,不一致时按 SKILL.md 的迁移规则处理(先备份本文件为带时间戳 .bak,再迁移,最后对话告知用户)
13
+ CONFIG_VERSION: 3 # 配置结构版本:skill 升级时若配置结构变化会递增;AI 每次执行前对比 SKILL.md「配置版本机制」节声明的当前版本,不一致时按 SKILL.md 的迁移规则处理(先备份本文件为带时间戳 .bak,再迁移,最后对话告知用户)
14
14
  FORMATS: [md, txt, html, content-png] # 落盘哪些格式(数组,可删减/增,如 [md, html] / [md, txt, html](不截图);content-png = 内容区截图(五张分节卡片整体,不含头部标题/复制按钮/页脚),删除该项即不截图;不影响对话中的 md 正文输出)
15
15
  DIR: auto # 落盘根目录:auto = 按当前系统自动选 DIR_MAC / DIR_WIN(也可直接写死某个绝对路径)
16
- DIR_MAC: /Users/luzhaosheng/MyWork/智慧食堂/reports # macOS 落盘根目录(自动按目标年度建子目录 annual-YYYY;目录不存在时回退用户主目录下 reports)
17
- DIR_WIN: d:\Workspace_QCoder\reports # Windows 落盘根目录(自动按目标年度建子目录 annual-YYYY;目录/盘符不存在时回退用户主目录下 reports)
16
+ DIR_MAC: ~/reports # macOS 落盘根目录(自动按目标年度建子目录 annual-YYYY;目录不存在时回退用户主目录下 reports)
17
+ DIR_WIN: %USERPROFILE%\reports # Windows 落盘根目录(自动按目标年度建子目录 annual-YYYY;目录/盘符不存在时回退用户主目录下 reports)
18
18
  OPEN_HTML: true # 落盘后是否自动用浏览器打开 html(FORMATS 不含 html 时忽略)
19
19
  THEME: tech # html 页面主题:tech 深蓝科技(默认)/ biz 浅色商务 / mono IDEA 黑亮 / light IDEA 白亮 / warm 温暖渐变;生成时写 <html data-theme="THEME值"> 定默认,页面右下角换肤坞五色点随点随换(浏览器本地记忆,?shot 截图模式自动隐藏,打印隐藏)
20
20
  TEMPLATE: default # 报告模板:default = 内置五段式(年度概览/核心成果与里程碑/经验与成长/不足与反思/新年展望与规划);custom = 使用下方「📝 自定义模板」节;口头临时指定模板仅当次生效
21
21
  ROLE: 全栈开发工程师(企业内技术开发) # 用户默认职业角色与主要工作内容(两者并存:职业名 + 括号内工作内容,生成内容/术语/量化指标/里程碑/风险话术全部按此画像走);用户随口描述职业时(如「我搞装修的,天天跑工地」)→ AI 提炼为规范表述(装修项目经理(负责工地现场管理、施工进度与质量巡检))更新此处;说「以 XX 的身份写」→ 当次临时换角色不改配置;说「以后默认用 XX 角色 / 我的职业是 XX / 我的主要工作是 XX」→ 永久更新此处
22
22
  CONFIRM: never # 落盘前确认:never = 直接生成落盘不确认(默认);text = 纯文字整理模式先出效果确认后再落盘;always = 任何方式生成都先确认;临时说「先看看效果」当次先确认、说「不用确认」当次跳过
23
+ DATA_SOURCES: [] # 数据源清单(升级不覆盖;AI 每次生成前 Read 本文件按此清单收集;空清单 = 只按会话/文字内容生成)。每项:name 唯一名称 + type 类型 + 路径。三种类型示例(把下方 # 注释示例改成你的真实数据源后填入上方数组):
24
+ # - name: 主项目仓库 # 名称:唯一 key(重名视为同一数据源;口述「只聚合 xxx」按 name 匹配)
25
+ # type: git # git = 代码仓库(git log 聚合提交)
26
+ # mac: ~/Projects/main-app # macOS 路径(绝对路径或 ~ 开头)
27
+ # win: D:\Projects\main-app # Windows 路径;「-」= 该系统不存在,自动跳过
28
+ # - name: 周例会纪要
29
+ # type: file # file = 普通文件/目录(直接 Read 内容聚合,适合文档/纪要/日志素材)
30
+ # mac: ~/Documents/meeting-notes.md
31
+ # win: -
32
+ # - name: 数据接口
33
+ # type: remote # remote = 远程网络源(AI 联网拉取 url 内容;仅生成时联网,HTML 产物仍零外链)
34
+ # url: https://example.com/data.json
23
35
  ```
24
36
 
25
37
  > 临时口头要求(仅对当次生效,不修改上方配置):说「不落盘/别写文件」→ 当次 DISK=false;说「写到桌面/存到 ~/report(macOS)或 D:\report(Windows)」→ 当次改用该 DIR;说「只要 md / 只出 html / 只要内容区截图」→ 当次只落指定格式;说「这次不截图」→ 当次不生成内容区截图;说「只要截图/重新截个图」→ 当次只对现有 html 执行内容区截图(不重新收集数据、不重写 md/txt/html 内容文件);说「别开浏览器」→ 当次 OPEN_HTML=false;说「这次按 xxx 模板来」→ 当次临时换模板(不改配置);说「以后都用这个模板」→ 自动写入下方「📝 自定义模板」节并把 TEMPLATE 改为 custom(永久生效);说「先看看效果/先出效果再落盘」→ 当次先出效果确认后再落盘;说「不用确认/直接落盘」→ 当次跳过确认直接落盘。说「页面用浅色商务主题/浅色主题」→ 当次 THEME=biz;说「以后默认用暖色主题」→ 永久改 THEME=warm。
@@ -0,0 +1,3 @@
1
+ # 升级时永不覆盖的用户可改文件(每行一个文件名,# 注释)
2
+ # 官方版有更新时另存 .upstream 对照,供手动合并
3
+ design-system.md
package/cli.js CHANGED
@@ -44,6 +44,22 @@ const SKIP_DIRS = new Set(["template", "node_modules", ".git", ".github"]);
44
44
  // 复制时排除的杂质(macOS 元数据 / 嵌套版本库目录)
45
45
  const COPY_EXCLUDE = new Set([".ds_store", ".git"]);
46
46
 
47
+ // 安装清单:记录上次安装的官方文件(相对路径)。升级清理只删清单内官方已删除的文件,
48
+ // 用户自建文件与清单外文件一律不动(无清单 = 旧版本安装,跳过清理,升级后补写)
49
+ const MANIFEST_FILE = ".installed-manifest";
50
+
51
+ function loadManifest(dest) {
52
+ const set = new Set();
53
+ const mf = path.join(dest, MANIFEST_FILE);
54
+ if (fs.existsSync(mf)) {
55
+ for (const line of fs.readFileSync(mf, "utf8").split(/\r?\n/)) {
56
+ const t = line.trim();
57
+ if (t && !t.startsWith("#")) set.add(t.toLowerCase());
58
+ }
59
+ }
60
+ return set;
61
+ }
62
+
47
63
  // ---------- 工具 ----------
48
64
 
49
65
  function expandHome(p) {
@@ -132,47 +148,53 @@ function stamp() {
132
148
  return "" + d.getFullYear() + p(d.getMonth() + 1) + p(d.getDate()) + "-" + p(d.getHours()) + p(d.getMinutes()) + p(d.getSeconds());
133
149
  }
134
150
 
135
- function copyDir(src, dest, preserve, hits, upstreams, genUpstream) {
151
+ // 复制官方技能文件;files 收集相对路径清单(供 .installed-manifest 安装清单)
152
+ function copyDir(src, dest, preserve, hits, upstreams, genUpstream, rel, files) {
136
153
  fs.mkdirSync(dest, { recursive: true });
137
154
  for (const entry of fs.readdirSync(src)) {
138
155
  if (COPY_EXCLUDE.has(entry.toLowerCase())) continue; // 跳过 .DS_Store 等杂质
139
156
  const s = path.join(src, entry);
140
157
  const d = path.join(dest, entry);
141
- if (fs.statSync(s).isDirectory()) copyDir(s, d, preserve, hits, upstreams, genUpstream);
142
- else if (preserve.has(entry.toLowerCase()) && fs.existsSync(d)) {
143
- hits.push(d);
144
- // 配置演进:官方版与本地版内容不同时,另存 .upstream 对照文件,供用户手动合并新配置点
145
- const sData = fs.readFileSync(s, "utf8");
146
- const dData = fs.readFileSync(d, "utf8");
147
- if (sData !== dData) {
148
- if (genUpstream !== false) {
149
- fs.writeFileSync(d + ".upstream", sData);
150
- upstreams.push(d + ".upstream");
158
+ const r = rel ? rel + "/" + entry : entry;
159
+ if (fs.statSync(s).isDirectory()) copyDir(s, d, preserve, hits, upstreams, genUpstream, r, files);
160
+ else {
161
+ files.push(r);
162
+ if (preserve.has(entry.toLowerCase()) && fs.existsSync(d)) {
163
+ hits.push(d);
164
+ // 配置演进:官方版与本地版内容不同时,另存 .upstream 对照文件,供用户手动合并新配置点
165
+ const sData = fs.readFileSync(s, "utf8");
166
+ const dData = fs.readFileSync(d, "utf8");
167
+ if (sData !== dData) {
168
+ if (genUpstream !== false) {
169
+ fs.writeFileSync(d + ".upstream", sData);
170
+ upstreams.push(d + ".upstream");
171
+ }
172
+ } else {
173
+ // 内容已一致(用户已手动合并或本就相同),旧对照文件已无意义
174
+ try { fs.unlinkSync(d + ".upstream"); } catch (e) {}
151
175
  }
152
- } else {
153
- // 内容已一致(用户已手动合并或本就相同),旧对照文件已无意义
154
- try { fs.unlinkSync(d + ".upstream"); } catch (e) {}
155
176
  }
177
+ else fs.copyFileSync(s, d);
156
178
  }
157
- else fs.copyFileSync(s, d);
158
179
  }
159
180
  }
160
181
 
161
- // 升级前清理:删除目标目录中官方已移除的文件(历史升级只增不删,废弃文件会残留)
162
- // 保护:preserve 清单文件、.upstream 对照、.bak- 备份、node_modules 依赖、COPY_EXCLUDE 项一律不动
163
- function pruneDir(src, dest, preserve) {
164
- if (!fs.existsSync(dest)) return;
182
+ // 升级前清理:删除官方已移除的文件(仅限安装清单内记录过的官方文件,用户自建文件不受影响)
183
+ // 保护:preserve 清单文件、.upstream 对照、.bak- 备份、node_modules 依赖、安装清单、COPY_EXCLUDE 项一律不动
184
+ function pruneDir(src, dest, preserve, manifest, rel) {
185
+ if (!fs.existsSync(dest) || manifest.size === 0) return; // 无清单(旧版本安装)跳过清理
165
186
  for (const entry of fs.readdirSync(dest)) {
166
187
  const lower = entry.toLowerCase();
167
188
  if (COPY_EXCLUDE.has(lower)) continue;
168
- if (lower === "node_modules" || lower.endsWith(".upstream") || lower.includes(".bak-")) continue;
189
+ if (lower === "node_modules" || lower === MANIFEST_FILE || lower.endsWith(".upstream") || lower.includes(".bak-")) continue;
169
190
  if (preserve.has(lower)) continue; // 用户文件永不删除
170
191
  const d = path.join(dest, entry);
171
192
  const s = path.join(src, entry);
193
+ const r = rel ? rel + "/" + entry : entry;
172
194
  if (fs.statSync(d).isDirectory()) {
173
- pruneDir(s, d, preserve);
195
+ pruneDir(s, d, preserve, manifest, r);
174
196
  if (fs.readdirSync(d).length === 0) fs.rmdirSync(d); // 清空后的目录一并删除
175
- } else if (!fs.existsSync(s)) {
197
+ } else if (!fs.existsSync(s) && manifest.has(r.toLowerCase())) {
176
198
  fs.unlinkSync(d);
177
199
  }
178
200
  }
@@ -332,8 +354,16 @@ async function upgradeSkill(src, dest, argv, existed) {
332
354
  try { fs.unlinkSync(localCfg + ".upstream"); } catch (e) {} // 旧对照已无意义,清理
333
355
  }
334
356
  const preserve = loadPreserveSet(src);
335
- if (existed) pruneDir(src, dest, preserve); // 先清理官方已删除的文件,再复制(只增不删 → 结构同步)
336
- copyDir(src, dest, preserve, hits, upstreams, mode !== "later"); // [3] 稍后处理不生成对照文件
357
+ const manifest = loadManifest(dest);
358
+ if (existed) pruneDir(src, dest, preserve, manifest); // 先清理官方已删除的文件(仅限安装清单内),再复制
359
+ const officialFiles = [];
360
+ copyDir(src, dest, preserve, hits, upstreams, mode !== "later", "", officialFiles); // [3] 稍后处理不生成对照文件
361
+ // 写安装清单:本次复制的官方文件(相对路径),下次升级据此精准清理官方已删文件,用户自建文件不受影响
362
+ officialFiles.sort((a, b) => a.localeCompare(b));
363
+ fs.writeFileSync(path.join(dest, MANIFEST_FILE),
364
+ "# SkillForge 安装清单:本次安装的官方文件(相对路径)\n" +
365
+ "# 升级清理仅限本清单内官方已删除的文件,用户自建文件不受影响\n" +
366
+ officialFiles.join("\n") + "\n");
337
367
 
338
368
  // 依赖提示:技能自带 package.json(如 deck-stage 依赖 PptxGenJS)且目标无 node_modules 时
339
369
  // (本地仓库直装会连带复制 node_modules 离线可用;npm 全局装出的包不含 node_modules)
@@ -528,6 +558,8 @@ function printHelp() {
528
558
  先备份你的配置为 user-config.md.bak-<时间戳>,再询问三选一——
529
559
  [1] 官方覆盖(备份在侧,随时找回)/ [2] 保留我的 + 官方版另存 .upstream 对照(默认)
530
560
  [3] 稍后处理(不生成对照文件);--yes 或非交互时默认 [2]
561
+ · 升级按 .installed-manifest 安装清单同步官方文件增删:只清理清单内官方已删除的文件,
562
+ 用户自建文件不动;旧版本安装无清单时跳过清理,升级后补写
531
563
 
532
564
  示例:
533
565
  skill-forge ls
@@ -12,7 +12,7 @@ disable-model-invocation: false
12
12
  ## 生成流程
13
13
 
14
14
  0.5 **周期歧义分流**:用户说「写总结/工作总结/写个汇报/做一份总结」等未言明周期的词 → AskUserQuestion 三选一(日报/周报/年报)确认周期再继续,不擅自默认
15
- 0. **读用户配置**(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION、自定义模板)→ 先 Read 同目录 `user-config.md`
15
+ 0. **读用户配置**(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION/DATA_SOURCES、自定义模板)→ 先 Read 同目录 `user-config.md`
16
16
  1. **解析日期**(自然语言 → 目标日期 YYYY-MM-DD)→ 读 `resources/date-parsing.md`
17
17
  2. **收集数据**(多源:会话口述 / 文字 / 文件 / 图片 / 代码提交记录,合并去重)→ 读 `resources/data-collection.md`
18
18
  3. **内容归类与润色**(聚合来源 / 补充任务 / 纯文字模式 / 输出格式 / 写作风格)→ 读 `resources/content-rules.md`
@@ -22,13 +22,13 @@ disable-model-invocation: false
22
22
 
23
23
  ## ⚙️ 配置与自定义模板
24
24
 
25
- **执行本 skill 前必须先 Read 同目录 `user-config.md`**:默认配置(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION)与自定义模板都在该文件中,以它为准。升级技能时 user-config.md 不会被覆盖,你的修改永久保留;官方更新配置时另存 `user-config.md.upstream` 对照文件,可按需手动合并新配置点。
25
+ **执行本 skill 前必须先 Read 同目录 `user-config.md`**:默认配置(DISK/FORMATS/DIR/OPEN_HTML/THEME/TEMPLATE/ROLE/CONFIRM/CONFIG_VERSION/DATA_SOURCES)与自定义模板都在该文件中,以它为准。升级技能时 user-config.md 不会被覆盖,你的修改永久保留;官方更新配置时另存 `user-config.md.upstream` 对照文件,可按需手动合并新配置点。
26
26
 
27
27
  - **THEME**:html 页面主题,tech 深蓝科技(默认)/ biz 浅色商务 / mono IDEA 黑亮 / light IDEA 白亮 / warm 温暖渐变;生成时写 `<html data-theme="THEME值">` 定默认,页面右下角换肤坞随点随换(localStorage 记忆、?shot 截图模式与打印隐藏)
28
28
 
29
29
  ## 配置版本机制(升级保护)
30
30
 
31
- 本 skill 当前配置版本为 `2`(对应 user-config.md 中的 `CONFIG_VERSION`)。执行时若发现 user-config.md 的 CONFIG_VERSION 与本节声明的当前版本不一致:
31
+ 本 skill 当前配置版本为 `3`(对应 user-config.md 中的 `CONFIG_VERSION`)。执行时若发现 user-config.md 的 CONFIG_VERSION 与本节声明的当前版本不一致:
32
32
 
33
33
  1. 先将旧 user-config.md 备份为 `user-config.md.bak-<时间戳>`(同目录,绝不删除旧值)
34
34
  2. 按本节「配置升级规则」迁移字段:新增字段补默认值、改名字段按映射改写、删除字段的值保留在备份中并在对话提示用户手动确认
@@ -39,7 +39,7 @@ disable-model-invocation: false
39
39
 
40
40
  **无法迁移项处理**(值域失效 / 语义漂移 / 数据不兼容):三情形——①旧值不在新值域(如旧模板/主题名已移除)②同名键含义变化(单位/枚举变更)③数据文件 schema 不兼容。三绝不:绝不静默(无法迁移项停下问,不猜值)、绝不丢失(旧值永远在 .bak-时间戳)、一次说清(升级报告三段式:⚠️ 版本与备份路径 → ✅ 已自动迁移清单 → 🟡 无法迁移项逐条附原因+影响+建议替代);随后 AskUserQuestion 三选项(A 用建议值 / B 用户给新值 / C 保持旧配置——不更新 CONFIG_VERSION,每次执行再提醒);报告必附回滚一句话;数据文件迁移前先复制 .bak-时间戳,能映射则映射、不能则写兼容层或留备份提示手动整理
41
41
 
42
- 当前版本变更记录:v1→v2 新增 THEME 字段(默认 tech;发现旧配置时按迁移规则补默认值)。
42
+ 当前版本变更记录:v1→v2 新增 THEME 字段(默认 tech;发现旧配置时按迁移规则补默认值)。v2→v3 新增 DATA_SOURCES 数据源清单段(默认空清单 + git/file/remote 三类型示例注释;DIR_MAC/DIR_WIN 默认值通用化——已配置用户保留原值不受影响)。
43
43
 
44
44
  ## 文档同步自检纪律(维护者必读)
45
45
 
@@ -8,7 +8,7 @@
8
8
  - 任务来源(默认):各仓库当日 提交记录自动聚合 + 本次会话中用户已提及/口述的工作内容 + 用户口头补充,全部合并去重;仅当用户明确说"只整理这段文字/只按这段"时才忽略提交记录与会话上下文、只用指定文字(见「纯文字整理模式」)
9
9
  - 「明日计划」取材双通道:①用户口述/文字补充的计划(优先并入);②一次生成连续多天日报时(本次批量生成中后面日期的日报,或 reports 目录中已存在的后续日报),从后一天日报的「今日任务进度」中抽取任务作为当天「明日计划」(抽取数量灵活、不设死上限:后续完成任务多且连续性强时可多抽至 4-5 条,少则抽 1-2 条,与后续日报内容形成呼应即可),描述改写为计划语气(完成态改进行态:如「完成 XX 重构」→「推进 XX 重构」「继续 XX 开发」,去掉量化数据/进度/用时);批量多天时优先保证跨天连续性:抽取时尽量让当天「明日计划」与后一天「今日任务进度」形成「计划→完成」的同主题承接链(如 11.05 计划「推进底部导航重构」→ 11.06 完成「完成底部导航重构」,同一条工作线前后呼应,跨天任务尽量串成连续的工作链);批量中最后一天无后续日报时,该段按口述或「暂无」处理
10
10
  - 量化数据取自 git --stat(文件数、增删行数);用时为合理估算(提交记录不记录耗时,估算值注明"约",可口头修正)
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 个仓库;无当日提交的仓库不写入
11
+ - 数据收集范围:按 user-config.md 的 DATA_SOURCES 清单收集(按当前系统自动选路径,另一系统的路径自动跳过);无当日提交的仓库不写入
12
12
  - HTML 版为参考图式深蓝面板卡片美化样式(实心深蓝卡片 + 细密水平条纹 + 上下边缘高光线 + 左缘节色条,保留 ask 同款发光动效):顶部「一键复制」按钮(复制纯文本版)+ TL;DR 摘要行、「今日任务进度」标题右侧带目标日期徽章 + 任务进度节内当日节奏条(上午/下午/晚上时段条,hover 显示时段提交明细)+ 节奏条下量化指标行(提交次数/涉及文件数/代码行数)+ 进度条终点圆点与流星扫描填充 + 液态玻璃卡片(@supports 兜底)+ CRT 扫描光带 + 全页 3D 微倾斜(±0.75°)、页脚署名 GENERATED BY SPECCORE TEAM(日期动态跟随目标日期),并随 FORMATS 默认落一张内容区截图 content-png(卡片整体 + 四周留白 + 日期徽章)
13
13
 
14
14
  ## 用户补充任务
@@ -1,27 +1,10 @@
1
1
  # 数据收集
2
2
 
3
- 先检测当前系统再取对应路径列(macOS:`uname -s` 返回 Darwin;Windows:`node -e "console.log(process.platform)"` 返回 win32),按需检查以下工作区当日提交,聚合产出。只汇总有提交的仓库:
3
+ 先检测当前系统(macOS:`uname -s` 返回 Darwin;Windows:`node -e "console.log(process.platform)"` 返回 win32),再 Read 同目录外的 `user-config.md` 顶部「默认配置」的 DATA_SOURCES 清单,按清单逐项收集(空清单 = 只按会话/文字内容生成)。每项按 type 分三种行为:
4
4
 
5
- | 仓库 | macOS 路径 | Windows 路径 |
6
- |---|---|---|
7
- | NearCast | /Users/luzhaosheng/SmartDeveloper/DevWorkspace/Android_Studio/NearCast | - |
8
- | nearcast-server | /Users/luzhaosheng/SmartDeveloper/DevWorkspace/IntelliJ_IDEA/nearcast-server | - |
9
- | nearcast-go | /Users/luzhaosheng/SmartDeveloper/DevWorkspace/GoProject/nearcast-go | - |
10
- | nearcast-admin | /Users/luzhaosheng/SmartDeveloper/DevWorkspace/WebProject/nearcast-admin | - |
11
- | SmartCanteenConsumerMachineApp | /Users/luzhaosheng/SmartDeveloper/DevWorkspace/Android_Studio/SmartCanteenConsumerMachineApp | - |
12
- | TrustPay | /Users/luzhaosheng/SmartDeveloper/DevWorkspace/Android_Studio/TrustPay | - |
13
- | srf-app | - | d:\Workspace_Java\srf-app |
14
- | srf-manage | - | d:\Workspace_Java\srf-manage |
15
- | srf-operation | - | d:\Workspace_Java\srf-operation |
16
- | srf-service | - | d:\Workspace_Java\srf-service |
17
- | srf-web-user | - | d:\Web_Projects\srf-web-user |
18
- | srf-web-operation | - | d:\Web_Projects\srf-web-operation |
19
- | srf-web-wx | - | d:\Web_Projects\srf-web-wx |
20
- | srf-web-h5-teacher | - | d:\Web_Projects\srf-web-h5-teacher |
21
- | srf-web-uop | - | d:\Web_Projects\srf-web-uop |
22
- | Spec-Core-Smart-Canteen | - | d:\Workspace_QCoder\Spec-Core-Smart-Canteen |
23
-
24
- - 「-」= 该仓库在当前系统不存在,跳过;当前系统对应列全为「-」(陌生机器)时跳过 提交记录收集,只按会话/文字内容生成
5
+ - git = 代码仓库:取 mac / win 中当前系统对应路径(「-」= 该系统不存在,跳过;当前系统全部为「-」的陌生机器时跳过 git 收集,只按会话/文字内容生成),用下方命令模板聚合该仓当日提交,只汇总有提交的仓库
6
+ - file = 普通文件/目录:直接 Read 内容(文档/纪要/日志等素材),提取要点并入
7
+ - remote = 远程网络源:AI 联网拉取 url 内容提取要点(仅收集时联网,HTML 产物仍零外链)
25
8
 
26
9
  命令模板:
27
10
 
@@ -34,7 +17,7 @@ git -C <仓库路径> log --since="YYYY-MM-DD 00:00:00" --until="YYYY-MM-DD 23:5
34
17
  - 同主题多提交(含多次提交与 MR 合并记录)合并为一条任务点,量化数据累加
35
18
  - 提交记录无法给出实际耗时,用时取合理估算值,允许用户事后修正
36
19
  - 无当日提交的仓库不写入日报
37
- - 仓库路径(当前系统列)不存在/非代码仓库时静默跳过该仓库(不报错、不写入)
38
- - 用户说「只写 xxx 的日报 / 只聚合 xxx 仓库」时只收集指定仓库
20
+ - 仓库路径(当前系统字段)不存在/非代码仓库时静默跳过该仓库(不报错、不写入)
21
+ - 用户说「只写 xxx 的日报 / 只聚合 xxx」时按 name 匹配只收集指定数据源
39
22
  - 提交记录之外的默认来源:本次会话中用户已提及/口述的工作内容(任务、进度、风险等对话信息)一并聚合,与 提交记录去重合并
40
23
  - 用户明确说"只整理这段文字/只按这段"时,忽略提交记录与会话上下文,只用指定文字
@@ -44,7 +44,7 @@
44
44
  - 词典外行业走兜底:按骨架 + 你提供的素材现场生成词条;说「记住这个行业」→ 固化为新词条
45
45
 
46
46
  ## 控制落盘(临时要求,仅对当次生效)
47
- - 默认:对话输出 Markdown + md/txt/html 三文件 + 内容区截图 content-png 落盘到 DIR(auto 按系统选:macOS=/Users/luzhaosheng/MyWork/reports、Windows=d:\Workspace_QCoder\reports)/<日期>/ + html 自动打开(DIR 目录/盘符不存在时自动改用用户主目录下 reports:macOS=~/reports、Windows=%USERPROFILE%\reports)
47
+ - 默认:对话输出 Markdown + md/txt/html 三文件 + 内容区截图 content-png 落盘到 DIR(auto 按系统选:macOS=~/reports、Windows=%USERPROFILE%\reports,模板默认值,实际以 user-config.md 为准)/<日期>/ + html 自动打开(DIR 目录/盘符不存在时自动改用用户主目录下 reports:macOS=~/reports、Windows=%USERPROFILE%\reports)
48
48
  - 说「写到桌面」→ 本次落盘到桌面(macOS=~/Desktop、Windows=%USERPROFILE%\Desktop);说「存到 ~/report / D:\report」→ 本次用指定目录(均自动按日期建子目录)
49
49
  - 说「不落盘/别写文件」→ 本次只在对话输出,不写文件、不开浏览器
50
50
  - 说「只要 md」「只出 html」「只要内容区截图」→ 本次只落指定格式文件;说「这次不截图」→ 本次跳过截图(content-png = 三张卡片整体一张图,四周约 40px 留白、「今日任务进度」标题右侧带目标日期徽章,不含头部标题、复制按钮、页脚)
@@ -57,7 +57,7 @@
57
57
  |---|---|---|
58
58
  | DISK | 是否落盘写文件 | true(落盘,默认)/ false(默认只在对话输出) |
59
59
  | FORMATS | 落盘哪些格式(数组) | [md, txt, html, content-png](默认,含内容区截图)/ [md, html] / [md, txt, html](不截图);content-png = 三张卡片整体截图(四周约 40px 留白、任务进度节带日期徽章),不含头部标题/复制按钮/页脚 |
60
- | DIR | 落盘根目录 | auto(按当前系统自动选 DIR_MAC / DIR_WIN,默认);DIR_MAC = macOS 根目录(/Users/luzhaosheng/MyWork/reports);DIR_WIN = Windows 根目录(d:\Workspace_QCoder\reports) |
60
+ | DIR | 落盘根目录 | auto(按当前系统自动选 DIR_MAC / DIR_WIN,默认);DIR_MAC = macOS 根目录(模板默认 ~/reports,可改);DIR_WIN = Windows 根目录(模板默认 %USERPROFILE%\reports,可改) |
61
61
  | OPEN_HTML | 落盘后是否自动打开 html | true(自动打开,默认)/ false(不打开) |
62
62
  | TEMPLATE | 报告模板 | default(内置三段式,默认)/ custom(按「📝 自定义模板」节的结构生成) |
63
63
  | CONFIRM | 落盘前先出效果确认 | never(直接生成不确认,默认)/ text(纯文字整理模式确认)/ always(所有生成都确认) |