harveyz-skill 0.1.2 → 0.2.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.
Files changed (31) hide show
  1. package/bin/cli.js +116 -44
  2. package/lib/bundles.js +97 -22
  3. package/lib/installer.js +126 -5
  4. package/lib/targets.js +1 -0
  5. package/lib/vars.js +34 -0
  6. package/package.json +6 -3
  7. package/skills/harness/diataxis-docs/SKILL.md +128 -0
  8. package/skills/harness/diataxis-docs/references/custom-categories.md +32 -0
  9. package/skills/harness/diataxis-docs/references/index-template.md +29 -0
  10. package/skills/web-fetch/article-fetcher/SKILL.md +625 -0
  11. package/skills/web-fetch/article-fetcher/references/article_utils.py +225 -0
  12. package/skills/web-fetch/article-fetcher/references/file-format.md +73 -0
  13. package/skills/web-fetch/article-fetcher/scripts/import_reading.py +75 -0
  14. package/skills/web-fetch/article-fetcher/scripts/init_db.py +33 -0
  15. package/skills/web-fetch/article-fetcher/scripts/url-index.db +0 -0
  16. package/skills/web-fetch/article-fetcher/scripts/url-index.db.bak +0 -0
  17. package/skills/web-fetch/article-fetcher/vars.json +12 -0
  18. package/skills/writing/mermaid-diagram/SKILL.md +220 -0
  19. package/skills/writing/mermaid-diagram/references/color-templates.md +75 -0
  20. package/skills/writing/mermaid-diagram/references/flowchart.md +88 -0
  21. package/skills/writing/mermaid-diagram/references/gantt-timeline.md +62 -0
  22. package/skills/writing/mermaid-diagram/references/other-charts.md +55 -0
  23. package/skills/writing/mermaid-diagram/references/sequence.md +143 -0
  24. package/skills/writing/mermaid-diagram/references/statediagram.md +54 -0
  25. package/skills/writing/mermaid-diagram/scripts/check_mermaid.py +84 -0
  26. package/tools/p-launch/p-launch.sh +275 -0
  27. package/tools/p-launch/tests/e2e.bats +164 -0
  28. package/tools/p-launch/tests/unit.bats +151 -0
  29. package/tools/p-launch/vars.json +9 -0
  30. package/tools/p-launch/zshrc.snippet +5 -0
  31. package/bundles.json +0 -24
@@ -0,0 +1,75 @@
1
+ # Roland Berger 配色标准
2
+
3
+ ## 色板总览
4
+
5
+ | 角色 | 用途 | fill | stroke |
6
+ |------|------|------|--------|
7
+ | **subgraph 上游** | 最底层 / 最重要 / 上游容器 | `#00205B` | `#1E4A9A` |
8
+ | **subgraph 中游** | 中间层 / 平台层容器 | `#003E96` | `#1A6AC4` |
9
+ | **subgraph 下游** | 应用层 / 端侧容器 | `#1E5C9E` | `#3A8ACC` |
10
+ | **节点 上游** | 上游 subgraph 内的节点 | `#0A2E7A` | `#1E4A9A` |
11
+ | **节点 中游** | 中游 subgraph 内的节点 | `#0050B8` | `#1A6AC4` |
12
+ | **节点 下游** | 下游 subgraph 内的节点 | `#2A6EAE` | `#3A8ACC` |
13
+
14
+ **规律**:同层的 subgraph 比其内节点颜色**深 10–15%**,形成层次感。文字颜色一律 `color:#fff`。
15
+
16
+ ---
17
+
18
+ ## 语义辅助色
19
+
20
+ 用于传达风险信号,叠加在主色体系之上:
21
+
22
+ | 语义 | 场景 | fill | stroke |
23
+ |------|------|------|--------|
24
+ | 预警 / 高风险 / 规避 | 危险区域、卖出信号 | `#7B1010` | `#B52020` |
25
+ | 机会 / 买入 / 低风险 | 买入区域、推荐配置 | `#1A5E3A` | `#2A7E50` |
26
+ | 等待 / 持有 / 中性 | 观察区域、中性态度 | `#003E96` | `#1A6AC4` |
27
+ | 投机 / 主题 / 高波动 | 高风险高回报区域 | `#2E0078` | `#5A20A0` |
28
+ | 价值 / 配置 / 稳健 | 价值投资区域 | `#004060` | `#1A5E80` |
29
+
30
+ ---
31
+
32
+ ## 使用规则
33
+
34
+ 1. **深色背景必须加白字**:任何 `fill` 颜色深于 `#4A4A4A`,必须加 `color:#fff`
35
+ 2. **单图最多 3 种主色**:不要同时使用上游/中游/下游/语义色全部五组
36
+ 3. **容器比节点深**:subgraph 的 fill 必须比其内节点的 fill 深,否则层次感消失
37
+ 4. **sequenceDiagram / gantt / timeline 不着色**:这些类型使用库默认颜色,不应用 RB 色板
38
+ 5. **语义色优先级低于主色**:只在需要传达明确风险信号时才使用语义辅助色
39
+
40
+ ---
41
+
42
+ ## style 片段速查
43
+
44
+ 三层结构(直接复制,按实际节点 ID 替换):
45
+
46
+ ```
47
+ style UP fill:#00205B,color:#fff,stroke:#1E4A9A
48
+ style MID fill:#003E96,color:#fff,stroke:#1A6AC4
49
+ style DOWN fill:#1E5C9E,color:#fff,stroke:#3A8ACC
50
+
51
+ style U1 fill:#0A2E7A,color:#fff,stroke:#1E4A9A
52
+ style M1 fill:#0050B8,color:#fff,stroke:#1A6AC4
53
+ style D1 fill:#2A6EAE,color:#fff,stroke:#3A8ACC
54
+ ```
55
+
56
+ 两层结构:
57
+
58
+ ```
59
+ style TOP fill:#00205B,color:#fff,stroke:#1E4A9A
60
+ style BOT fill:#003E96,color:#fff,stroke:#1A6AC4
61
+
62
+ style T1 fill:#0A2E7A,color:#fff,stroke:#1E4A9A
63
+ style B1 fill:#0050B8,color:#fff,stroke:#1A6AC4
64
+ ```
65
+
66
+ 语义色(按需挑选):
67
+
68
+ ```
69
+ style X fill:#7B1010,color:#fff,stroke:#B52020 /* 预警红 */
70
+ style X fill:#1A5E3A,color:#fff,stroke:#2A7E50 /* 机会绿 */
71
+ style X fill:#2E0078,color:#fff,stroke:#5A20A0 /* 投机紫 */
72
+ style X fill:#004060,color:#fff,stroke:#1A5E80 /* 价值蓝绿 */
73
+ ```
74
+
75
+ > 含真实内容的完整产业链示例 → `references/flowchart.md`
@@ -0,0 +1,88 @@
1
+ # flowchart 详细规则与布局技法
2
+
3
+ ## 基本语法
4
+
5
+ ```yaml
6
+ 方向: TD 优先;LR 仅用于天然横向内容
7
+ 节点: ["标签"] 格式,标签内用 <br/> 换行
8
+ 子图: subgraph ID["显示名"] ... end
9
+ 颜色: style NodeID fill:#xxx,color:#fff,stroke:#xxx
10
+ 边: --> 有向;--- 无向(用于矩阵配对);-.-> 虚线
11
+ 禁止: emoji, ·, →, direction TB in subgraph
12
+ ```
13
+
14
+ ## 矩阵布局(subgraph 内 2 列网格)
15
+
16
+ 当 subgraph 内节点 ≥ 4 个时,用 `---`(无向边)配对强制 2 列布局:
17
+
18
+ ```mermaid
19
+ flowchart TD
20
+ subgraph LAYER["层级名称"]
21
+ A["节点A"] --- B["节点B"]
22
+ C["节点C"] --- D["节点D"]
23
+ E["单数节点(居中)"]
24
+ end
25
+ ```
26
+
27
+ - `---` 产生细线连接,视觉上表示"同组"
28
+ - 奇数节点放最后一行,独立居中
29
+ - 严禁 4 个或以上节点堆在同一无连接行(会横向撑满)
30
+
31
+ ## subgraph 间箭头
32
+
33
+ ```mermaid
34
+ flowchart TD
35
+ subgraph UP["上游"] end
36
+ subgraph MID["中游"] end
37
+ subgraph DOWN["下游"] end
38
+
39
+ UP -->|"标签"| MID
40
+ MID -->|"标签"| DOWN
41
+ ```
42
+
43
+ - subgraph ID 可直接作为箭头端点(Mermaid v9+)
44
+ - 层间箭头标签保持**单行短语**,不用 `\n`
45
+
46
+ ## 多行节点标签
47
+
48
+ ```
49
+ ✅ A["第一行<br/>第二行<br/>第三行"]
50
+ ❌ A["第一行\n第二行\n第三行"] ← \n 在部分渲染器失效
51
+ ```
52
+
53
+ ---
54
+
55
+ ## 完整示例:三层产业链板块地图
56
+
57
+ ```mermaid
58
+ flowchart TD
59
+ subgraph UP["上游 算力基础设施"]
60
+ U1["AI芯片 / 晶圆代工<br/>NVIDIA AMD Broadcom<br/>寒武纪 海光"] --- U2["设备 / 存储 HBM<br/>ASML 北方华创<br/>SK海力士 Micron"]
61
+ U3["光模块 / 服务器<br/>中际旭创 新易盛<br/>工业富联 Dell"] --- U4["IDC / 液冷 / 电力<br/>英维克 Vertiv<br/>阳光电源 VST"]
62
+ end
63
+
64
+ subgraph MID["中游 模型与平台"]
65
+ M1["大模型<br/>GPT Gemini 通义 DeepSeek"] --- M2["云平台<br/>Azure AWS 阿里云 腾讯云"]
66
+ end
67
+
68
+ subgraph DOWN["下游 应用与端侧"]
69
+ D1["企业SaaS<br/>Palantir ServiceNow<br/>金山办公"] --- D2["AI编程 / 搜索<br/>Copilot Cursor Google"]
70
+ D3["端侧硬件<br/>机器人 智驾 AI眼镜"]
71
+ end
72
+
73
+ UP -->|"卖铲子"| MID
74
+ MID -->|"挖金子"| DOWN
75
+
76
+ style UP fill:#00205B,color:#fff,stroke:#1E4A9A
77
+ style MID fill:#003E96,color:#fff,stroke:#1A6AC4
78
+ style DOWN fill:#1E5C9E,color:#fff,stroke:#3A8ACC
79
+ style U1 fill:#0A2E7A,color:#fff,stroke:#1E4A9A
80
+ style U2 fill:#0A2E7A,color:#fff,stroke:#1E4A9A
81
+ style U3 fill:#0A2E7A,color:#fff,stroke:#1E4A9A
82
+ style U4 fill:#0A2E7A,color:#fff,stroke:#1E4A9A
83
+ style M1 fill:#0050B8,color:#fff,stroke:#1A6AC4
84
+ style M2 fill:#0050B8,color:#fff,stroke:#1A6AC4
85
+ style D1 fill:#2A6EAE,color:#fff,stroke:#3A8ACC
86
+ style D2 fill:#2A6EAE,color:#fff,stroke:#3A8ACC
87
+ style D3 fill:#2A6EAE,color:#fff,stroke:#3A8ACC
88
+ ```
@@ -0,0 +1,62 @@
1
+ # gantt / timeline 详细规则与示例
2
+
3
+ ## gantt
4
+
5
+ ```yaml
6
+ 日期格式: dateFormat YYYY-MM-DD(必须,不可用 YYYY-Q 或其他格式)
7
+ 轴标签: axisFormat %Y(年份粒度)或 %b %Y(月份+年份)
8
+ 默认不写则渲染器自选,通常不美观,建议显式声明
9
+ 状态: done(已完成)/ active(进行中)/ 空(未来计划)
10
+ 任务ID: ASCII,不含特殊字符
11
+ 中文任务名: 直接写在 : 前,可以含中文
12
+ ```
13
+
14
+ 示例:
15
+
16
+ ```mermaid
17
+ gantt
18
+ title GPU芯片技术迭代
19
+ dateFormat YYYY-MM-DD
20
+ axisFormat %Y
21
+
22
+ section 英伟达 NVIDIA
23
+ A100 :done, nv1, 2020-04-01, 2022-09-01
24
+ H100 :done, nv2, 2022-09-01, 2024-06-01
25
+ B100 :active, nv3, 2024-06-01, 2026-01-01
26
+
27
+ section AMD
28
+ MI250 :done, amd1, 2021-11-01, 2023-12-01
29
+ MI300 :active, amd2, 2023-12-01, 2025-06-01
30
+ ```
31
+
32
+ **axisFormat 选择原则:**
33
+ - 跨度 ≥ 3 年 → `%Y`(只显示年份,不拥挤)
34
+ - 跨度 3–18 个月 → `%b %Y`(月份缩写 + 年份)
35
+ - 跨度 < 3 个月 → `%m-%d`
36
+
37
+ ---
38
+
39
+ ## timeline
40
+
41
+ ```yaml
42
+ 结构: timeline → title → section(可选)→ key : event1 \n : event2
43
+ key: 纯文本,不含 + % & 等特殊字符
44
+ section: 分组用,可选
45
+ 注意: 不支持自定义颜色;渲染为垂直时间轴,天然窄页友好
46
+ ```
47
+
48
+ 示例:
49
+
50
+ ```
51
+ timeline
52
+ title AI 大模型发展里程碑
53
+ section 2022
54
+ ChatGPT 发布 : OpenAI 推出对话式 AI
55
+ : 用户量 1 亿破纪录
56
+ section 2023
57
+ GPT-4 发布 : 多模态能力
58
+ Claude 2 : Anthropic 发布
59
+ section 2024
60
+ o1 系列 : 推理模型时代开启
61
+ DeepSeek R1 : 开源推理模型
62
+ ```
@@ -0,0 +1,55 @@
1
+ # quadrantChart / mindmap 详细规则
2
+
3
+ ## quadrantChart
4
+
5
+ ```yaml
6
+ quadrant标签: 不含 / & → 等字符
7
+ ❌ quadrant-3 减仓/规避
8
+ ✅ quadrant-3 减仓规避
9
+ 点标签: "标签名: [x, y]",x/y 在 0.0–1.0 之间
10
+ 中文标签可用,但不能有冒号之外的特殊字符
11
+ ```
12
+
13
+ 示例:
14
+
15
+ ```mermaid
16
+ quadrantChart
17
+ title 板块配置矩阵
18
+ x-axis 确定性低 --> 确定性高
19
+ y-axis 弹性低 --> 弹性高
20
+ quadrant-1 重仓配置
21
+ quadrant-2 高风险高回报
22
+ quadrant-3 规避区域
23
+ quadrant-4 低配持有
24
+ AI算力: [0.8, 0.9]
25
+ 新能源: [0.5, 0.6]
26
+ 消费: [0.3, 0.3]
27
+ ```
28
+
29
+ ---
30
+
31
+ ## mindmap
32
+
33
+ ```yaml
34
+ 缩进: 严格 2 空格/级,不混用 tab
35
+ 节点文本: 纯文本,不含 : ( ) [ ] { } 等 Mermaid 控制字符
36
+ root: root((显示文本)) 圆形;root[文本] 方形
37
+ 分隔符: 同级用空格,不用 · / → 等
38
+ ```
39
+
40
+ 示例:
41
+
42
+ ```mermaid
43
+ mindmap
44
+ root((AI产业))
45
+ 算力层
46
+ 芯片
47
+ 存储
48
+ 服务器
49
+ 模型层
50
+ 基础模型
51
+ 微调模型
52
+ 应用层
53
+ 企业软件
54
+ 消费应用
55
+ ```
@@ -0,0 +1,143 @@
1
+ # sequenceDiagram 详细规则与示例
2
+
3
+ ## 基本语法
4
+
5
+ ```yaml
6
+ 参与者: participant A as 显示名(推荐)或 participant "含空格/中文名"
7
+ 角色图标: actor 替代 participant,渲染为火柴人(人类角色用 actor,系统用 participant)
8
+ 箭头: ->> 同步调用(实线箭头)
9
+ -->> 返回/异步响应(虚线箭头)
10
+ -x 消息丢失(实线+X,表示失败/超时)
11
+ --x 异步失败
12
+ 激活框: activate A ... deactivate A (或缩写 ->>+ / ->>-)
13
+ 编号: autonumber(在 sequenceDiagram 下一行加此关键字)
14
+ ```
15
+
16
+ ## 最重要规则:参与者名称
17
+
18
+ 含中文、空格或特殊字符的参与者名必须处理,否则语法报错:
19
+
20
+ ```
21
+ ✅ participant U as 用户
22
+ ✅ participant "用户服务"
23
+ ✅ actor Client as 客户端
24
+ ❌ participant 用户服务 ← 中文无引号,部分渲染器报错
25
+ ❌ participant User Service ← 空格无引号,报错
26
+ ```
27
+
28
+ **推荐用 alias 语法(`X as 显示名`)而非引号**:ID 保持 ASCII,显示名随意。
29
+
30
+ ## activate / deactivate 配对规则
31
+
32
+ 每个 `activate X` 必须有对应的 `deactivate X`,否则激活框会无限叠加:
33
+
34
+ ```mermaid
35
+ sequenceDiagram
36
+ participant C as 客户端
37
+ participant S as 服务端
38
+
39
+ C ->> S: 请求
40
+ activate S
41
+ S -->> C: 响应
42
+ deactivate S
43
+ ```
44
+
45
+ **简写形式**(`->>+` 等价于发送后 activate,`-->>-` 等价于返回后 deactivate):
46
+
47
+ ```mermaid
48
+ sequenceDiagram
49
+ participant C as 客户端
50
+ participant S as 服务端
51
+
52
+ C ->>+ S: 请求
53
+ S -->>- C: 响应
54
+ ```
55
+
56
+ ## 条件 / 循环 / 并行块
57
+
58
+ 所有块必须以 `end` 关闭:
59
+
60
+ ```mermaid
61
+ sequenceDiagram
62
+ participant C as 客户端
63
+ participant S as 服务端
64
+ participant DB as 数据库
65
+
66
+ C ->> S: 查询用户
67
+
68
+ alt 缓存命中
69
+ S -->> C: 返回缓存
70
+ else 缓存未命中
71
+ S ->> DB: 查询数据库
72
+ activate DB
73
+ DB -->> S: 返回数据
74
+ deactivate DB
75
+ S -->> C: 返回结果
76
+ end
77
+
78
+ loop 每5分钟心跳
79
+ C ->> S: ping
80
+ S -->> C: pong
81
+ end
82
+
83
+ par 并行操作
84
+ S ->> DB: 写日志
85
+ and
86
+ S ->> S: 更新缓存
87
+ end
88
+ ```
89
+
90
+ ## Note 注释
91
+
92
+ ```
93
+ Note right of A: 文字 ← A 右侧
94
+ Note left of A: 文字 ← A 左侧
95
+ Note over A,B: 跨越 A 和 B ← 跨多个参与者
96
+ ```
97
+
98
+ ## 窄页宽度控制
99
+
100
+ sequenceDiagram 天然横向排列,参与者越多越宽:
101
+
102
+ - **≤ 5 个参与者**可适配 700–900px 的 Markdown 窄页
103
+ - 超过 5 个时,考虑拆成两张图或用 `destroy` 提前移除不再需要的参与者
104
+
105
+ ## 禁止事项
106
+
107
+ ```
108
+ ❌ 消息文本内换行(\n / <br/>) → sequenceDiagram 消息只支持单行
109
+ ❌ activate 未配对 deactivate → 会产生叠加激活框 bug
110
+ ❌ 中文/空格参与者名不加处理 → 用 alias 或引号
111
+ ❌ 禁用字符(· → — "" emoji) → 同其他图类型规则
112
+ ❌ 自定义颜色(style/classDef) → sequenceDiagram 不支持节点着色
113
+ ```
114
+
115
+ ## 完整示例:API 调用时序
116
+
117
+ ```mermaid
118
+ sequenceDiagram
119
+ autonumber
120
+ actor U as 用户
121
+ participant G as API网关
122
+ participant A as 认证服务
123
+ participant B as 业务服务
124
+ participant DB as 数据库
125
+
126
+ U ->>+ G: POST /api/order
127
+ G ->>+ A: 验证 Token
128
+ A -->>- G: Token 有效
129
+
130
+ G ->>+ B: 创建订单
131
+ B ->>+ DB: INSERT order
132
+ DB -->>- B: 成功
133
+
134
+ alt 库存充足
135
+ B -->>- G: 订单ID: 12345
136
+ G -->>- U: 200 创建成功
137
+ else 库存不足
138
+ B -->>- G: 错误: 库存不足
139
+ G -->>- U: 400 库存不足
140
+ end
141
+
142
+ Note over B,DB: 异步写入审计日志
143
+ ```
@@ -0,0 +1,54 @@
1
+ # stateDiagram-v2 详细规则与示例
2
+
3
+ ## 基本语法
4
+
5
+ ```yaml
6
+ 方向: direction TB(不用 LR,否则横向过宽)
7
+ state ID: 只用 ASCII(S1 S2 Idle 等)
8
+ 显示文本: state "中文描述" as ASCII_ID
9
+ 转换标签: S1 --> S2 : 简短描述(单行,无 → / 等特殊字符)
10
+ ```
11
+
12
+ ## 为什么 state ID 必须是 ASCII
13
+
14
+ Mermaid 解析器对中文 state ID 的支持不稳定——某些渲染器(如 GitHub、Notion)
15
+ 会报语法错误或产生乱码。始终用 ASCII ID + `state "..." as ID` 语法:
16
+
17
+ ```mermaid
18
+ stateDiagram-v2
19
+ direction TB
20
+ [*] --> S1
21
+ state "概念炒作阶段 PE 30x to 100x+" as S1
22
+ state "业绩验证阶段" as S2
23
+ S1 --> S2 : 财报兑现
24
+ S2 --> S1 : 预期落空
25
+ ```
26
+
27
+ ## 语义配色(classDef)
28
+
29
+ ```mermaid
30
+ stateDiagram-v2
31
+ direction TB
32
+ classDef opportunity fill:#1A5E3A,stroke:#2A7E50,color:#fff
33
+ classDef hold fill:#003E96,stroke:#1A6AC4,color:#fff
34
+ classDef danger fill:#7B1010,stroke:#B52020,color:#fff
35
+
36
+ state "买入区" as S1
37
+ state "持有区" as S2
38
+ state "规避区" as S3
39
+
40
+ [*] --> S1
41
+ S1 --> S2 : 价格回升
42
+ S2 --> S3 : 估值透支
43
+ S3 --> S1 : 回调充分
44
+
45
+ class S1 opportunity
46
+ class S2 hold
47
+ class S3 danger
48
+ ```
49
+
50
+ ## 注意事项
51
+
52
+ - `note right of / left of` 语法部分渲染器不支持,谨慎使用
53
+ - 转换标签(`:` 后)避免 `/`、`→`、`<`、`>` 等特殊字符
54
+ - 不使用 nested state(嵌套状态)——渲染不稳定
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Mermaid block validator — checks for known fatal characters and syntax errors.
4
+
5
+ Usage:
6
+ python check_mermaid.py report.md
7
+ python check_mermaid.py *.md
8
+ """
9
+
10
+ import re
11
+ import sys
12
+
13
+ RISKY_CHARS = {
14
+ '·': 'middle-dot ·',
15
+ '→': 'arrow →',
16
+ '—': 'em-dash —',
17
+ '“': 'left-quote "',
18
+ '”': 'right-quote "',
19
+ }
20
+
21
+
22
+ def check_mermaid_blocks(md_content: str) -> list[str]:
23
+ blocks = re.findall(r'```mermaid\n(.*?)```', md_content, re.DOTALL)
24
+ issues = []
25
+
26
+ for i, block in enumerate(blocks, 1):
27
+ dtype = block.strip().split('\n')[0]
28
+ label = f"图{i} [{dtype}]"
29
+
30
+ for ch, name in RISKY_CHARS.items():
31
+ if ch in block:
32
+ issues.append(f"{label}: 含禁用字符 {name}")
33
+
34
+ if 'flowchart' in dtype or 'graph' in dtype:
35
+ if re.search(r'"[^"]*\\n[^"]*"', block):
36
+ issues.append(f"{label}: 节点标签含 \\n,应改 <br/>")
37
+
38
+ if 'flowchart LR' in block:
39
+ issues.append(f"{label}: 使用横向 LR,评估是否需改 TD")
40
+
41
+ if 'direction LR' in block and 'stateDiagram' in dtype:
42
+ issues.append(f"{label}: stateDiagram 使用 direction LR,建议改 TB")
43
+
44
+ if 'quadrantChart' in dtype and re.search(r'quadrant-\d[^#\n]*/[^#\n]*', block):
45
+ issues.append(f"{label}: quadrant 标签含 /")
46
+
47
+ if 'gantt' in dtype and re.search(r'\d{4}-Q\d', block):
48
+ issues.append(f"{label}: gantt 使用 YYYY-Q 格式,应改 YYYY-MM-DD")
49
+
50
+ if 'stateDiagram' in dtype:
51
+ lines = block.split('\n')
52
+ for line in lines:
53
+ line = line.strip()
54
+ if line.startswith('state ') and ' as ' not in line:
55
+ state_id = line.split()[1].strip('"\'')
56
+ if any(ord(c) > 127 for c in state_id):
57
+ issues.append(f"{label}: state ID 含中文,应用 ASCII ID + as 别名")
58
+
59
+ return issues
60
+
61
+
62
+ def main():
63
+ if len(sys.argv) < 2:
64
+ print("Usage: python check_mermaid.py <file.md> [file2.md ...]")
65
+ sys.exit(1)
66
+
67
+ all_clean = True
68
+ for path in sys.argv[1:]:
69
+ with open(path, encoding='utf-8') as f:
70
+ content = f.read()
71
+ issues = check_mermaid_blocks(content)
72
+ if issues:
73
+ all_clean = False
74
+ print(f"\n{path}:")
75
+ for issue in issues:
76
+ print(f" ❌ {issue}")
77
+ else:
78
+ print(f"{path}: ✅ 通过")
79
+
80
+ sys.exit(0 if all_clean else 1)
81
+
82
+
83
+ if __name__ == '__main__':
84
+ main()