psyclaw 0.29.5 → 0.29.6
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 +4 -4
- package/dist/src/branding.js +1 -1
- package/dist/src/branding.js.map +1 -1
- package/dist/src/session/help.js +2 -2
- package/dist/src/session/help.js.map +1 -1
- package/dist/src/style/cli-ui.js +1 -1
- package/dist/src/style/cli-ui.js.map +1 -1
- package/package.json +1 -3
- package/skills/recommended/catalog.json +20 -2
- package/skills/scholars/README.md +20 -13
- package/skills/scholars/freud-perspective/SKILL.md +3 -3
- package/skills/scholars/gelman-perspective/SKILL.md +3 -3
- package/skills/scholars/kahneman-perspective/SKILL.md +3 -3
- package/vendor/nuwa-skill/LICENSE +0 -21
- package/vendor/nuwa-skill/NOTICE.md +0 -9
- package/vendor/nuwa-skill/PROVENANCE.json +0 -1
- package/vendor/nuwa-skill/README.md +0 -378
- package/vendor/nuwa-skill/README_EN.md +0 -290
- package/vendor/nuwa-skill/SKILL.md +0 -709
- package/vendor/nuwa-skill/references/extraction-framework.md +0 -151
- package/vendor/nuwa-skill/references/fidelity-scorecard.md +0 -63
- package/vendor/nuwa-skill/references/skill-template.md +0 -117
- package/vendor/nuwa-skill/scripts/merge_research.py +0 -150
- package/vendor/nuwa-skill/scripts/quality_check.py +0 -152
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
# 思维框架提炼方法论
|
|
2
|
-
|
|
3
|
-
> 从原始信息到可运行的心智模型,核心方法论
|
|
4
|
-
|
|
5
|
-
## 一、心智模型识别的三重验证
|
|
6
|
-
|
|
7
|
-
一个论点要被认定为「心智模型」而非「随口一说」,必须通过三重验证:
|
|
8
|
-
|
|
9
|
-
### 验证1: 跨域复现
|
|
10
|
-
同一个思维框架出现在此人讨论的至少2个不同领域。
|
|
11
|
-
|
|
12
|
-
例:纳瓦尔的「杠杆」概念——
|
|
13
|
-
- 在财富创造中谈杠杆(代码、媒体、资本、劳动力)
|
|
14
|
-
- 在个人成长中谈杠杆(特定知识 + 杠杆 = 复利)
|
|
15
|
-
- 在职业选择中谈杠杆(选择有杠杆效应的工作)
|
|
16
|
-
→ 跨3个领域复现 → 这是真正的心智模型
|
|
17
|
-
|
|
18
|
-
### 验证2: 有生成力
|
|
19
|
-
用这个模型可以推断此人对新问题的可能立场。
|
|
20
|
-
|
|
21
|
-
例:如果芒格的「逆向思维」是心智模型——
|
|
22
|
-
- 面对「如何成功」→ 他会先想「如何确保失败」
|
|
23
|
-
- 面对「如何投资」→ 他会先想「如何亏光所有钱」
|
|
24
|
-
→ 能生成新推断 → 这是真正的心智模型
|
|
25
|
-
|
|
26
|
-
### 验证3: 有排他性
|
|
27
|
-
不是所有聪明人都会这样想,这个模型体现了此人的独特视角。
|
|
28
|
-
|
|
29
|
-
例:「反脆弱」是塔勒布的,不是所有人都这样看世界
|
|
30
|
-
→ 有区分度 → 这是值得提炼的心智模型
|
|
31
|
-
|
|
32
|
-
**如果一个观点只通过了1重验证** → 降级为「决策启发式」而非「心智模型」
|
|
33
|
-
**如果一个观点0重验证都没过** → 可能只是此人在特定场景说的话,不纳入
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## 二、表达DNA的量化方法
|
|
38
|
-
|
|
39
|
-
### 2.1 句式指纹
|
|
40
|
-
|
|
41
|
-
从此人的长文/演讲中随机抽取20个段落,统计:
|
|
42
|
-
|
|
43
|
-
| 维度 | 测量方式 |
|
|
44
|
-
|------|---------|
|
|
45
|
-
| 平均句长 | 字数/句数 |
|
|
46
|
-
| 疑问句比例 | 疑问句数/总句数 |
|
|
47
|
-
| 类比密度 | 类比数/千字 |
|
|
48
|
-
| 第一人称使用率 | 「我」出现频率 |
|
|
49
|
-
| 确定性语气比例 | 「一定」「显然」vs「也许」「可能」 |
|
|
50
|
-
| 转折频率 | 「但是」「然而」「不过」/千字 |
|
|
51
|
-
|
|
52
|
-
### 2.2 风格标签
|
|
53
|
-
|
|
54
|
-
从以下维度打标:
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
正式 ←→ 口语
|
|
58
|
-
抽象 ←→ 具体
|
|
59
|
-
谨慎 ←→ 断言
|
|
60
|
-
学术 ←→ 通俗
|
|
61
|
-
长句 ←→ 短句
|
|
62
|
-
铺垫型 ←→ 结论先行
|
|
63
|
-
数据驱动 ←→ 叙事驱动
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### 2.3 禁忌词和口癖
|
|
67
|
-
|
|
68
|
-
- 此人从不用的词 → 生成Skill时也不用
|
|
69
|
-
- 此人的口癖/高频表达 → 适度使用(太多变成模仿秀)
|
|
70
|
-
|
|
71
|
-
---
|
|
72
|
-
|
|
73
|
-
## 三、矛盾处理原则
|
|
74
|
-
|
|
75
|
-
矛盾是人格的核心特征,不是需要修复的Bug。
|
|
76
|
-
|
|
77
|
-
### 三种矛盾类型
|
|
78
|
-
|
|
79
|
-
1. **时间性矛盾**(观点演化)
|
|
80
|
-
- 此人早期说A,后来说B
|
|
81
|
-
- 处理:记录演化轨迹,标注「早期」「近期」
|
|
82
|
-
- 在Skill中以「近期观点」为主,但提及演化
|
|
83
|
-
|
|
84
|
-
2. **领域性矛盾**(不同场景不同规则)
|
|
85
|
-
- 此人在工作中主张X,在生活中主张Y
|
|
86
|
-
- 处理:分领域记录,不强求统一
|
|
87
|
-
- 这恰恰是深度的来源
|
|
88
|
-
|
|
89
|
-
3. **本质性张力**(价值观内在冲突)
|
|
90
|
-
- 例:既追求自由又重视纪律
|
|
91
|
-
- 处理:明确记录为「核心张力」
|
|
92
|
-
- 这通常是此人最有意思的部分
|
|
93
|
-
|
|
94
|
-
### 错误的处理方式
|
|
95
|
-
- ❌ 选一边忽略另一边
|
|
96
|
-
- ❌ 编一个调和的解释
|
|
97
|
-
- ❌ 假装矛盾不存在
|
|
98
|
-
|
|
99
|
-
---
|
|
100
|
-
|
|
101
|
-
## 四、信息不足时的处理
|
|
102
|
-
|
|
103
|
-
| 情况 | 处理 |
|
|
104
|
-
|------|------|
|
|
105
|
-
| 某个维度公开信息很少 | 在Skill中标注「信息不足,此维度为推测」 |
|
|
106
|
-
| 只有二手信息 | 降低置信度,标注为「据[来源]报道」 |
|
|
107
|
-
| 信息相互矛盾且无法判断 | 并列呈现,让用户自行判断 |
|
|
108
|
-
| 此人刻意不公开某方面 | 尊重边界,在Skill中注明「此人对这个话题保持沉默」 |
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## 五、人物Skill vs 主题Skill的区别
|
|
113
|
-
|
|
114
|
-
| 维度 | 人物Skill | 主题Skill |
|
|
115
|
-
|------|----------|----------|
|
|
116
|
-
| 核心 | 一个人的思维方式 | 一个领域的思维工具箱 |
|
|
117
|
-
| 心智模型来源 | 主要来自一个人 | 综合多人视角 |
|
|
118
|
-
| 表达风格 | 模拟此人的表达 | 中性但专业 |
|
|
119
|
-
| 矛盾处理 | 保留个人内在矛盾 | 呈现流派间分歧 |
|
|
120
|
-
| 验证方式 | 对比此人已知立场 | 对比领域内共识 |
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## 六、质量自检清单
|
|
125
|
-
|
|
126
|
-
生成Skill后,用以下问题自检:
|
|
127
|
-
|
|
128
|
-
### 心智模型
|
|
129
|
-
- [ ] 每个模型都有至少2个不同领域的证据?
|
|
130
|
-
- [ ] 模型数量在3-7个之间?(太少=太浅,太多=没提炼)
|
|
131
|
-
- [ ] 每个模型都有明确的应用场景和局限?
|
|
132
|
-
- [ ] 模型之间有张力但不矛盾?
|
|
133
|
-
|
|
134
|
-
### 表达DNA
|
|
135
|
-
- [ ] 读起来有辨识度,不像通用AI?
|
|
136
|
-
- [ ] 没有过度模仿变成caricature?
|
|
137
|
-
- [ ] 抓住了核心特征而非表面模仿?
|
|
138
|
-
|
|
139
|
-
### 决策启发式
|
|
140
|
-
- [ ] 每条规则都有具体案例支撑?
|
|
141
|
-
- [ ] 可以被新情况触发(不只适用于原始案例)?
|
|
142
|
-
|
|
143
|
-
### 诚实边界
|
|
144
|
-
- [ ] 明确写了做不到什么?
|
|
145
|
-
- [ ] 标注了信息源和调研时间?
|
|
146
|
-
- [ ] 承认了信息不足的维度?
|
|
147
|
-
|
|
148
|
-
### 整体
|
|
149
|
-
- [ ] 用此人的眼睛看一个新问题,能得到有价值的视角?
|
|
150
|
-
- [ ] 不是此人原话的拼凑,而是框架的运行?
|
|
151
|
-
- [ ] 删掉名字后,还能认出这是谁的思维方式?
|
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
# 保真度评分卡(Fidelity Scorecard)
|
|
2
|
-
|
|
3
|
-
> 人物Skill的出厂质检报告。回答一个问题:**这个skill跑起来到底像不像、诚不诚实?**
|
|
4
|
-
>
|
|
5
|
-
> 背景:SkillLens论文(arXiv 2605.23899)实证,LLM自评skill质量准确率仅46.4%(接近随机)。所以评分卡的铁律是:**答题agent和评分agent必须是两个独立agent,绝不自评自证。**
|
|
6
|
-
|
|
7
|
-
## 五个维度(总分100)
|
|
8
|
-
|
|
9
|
-
| # | 维度 | 分值 | 测什么 | 怎么测 |
|
|
10
|
-
|---|------|------|--------|--------|
|
|
11
|
-
| 1 | 立场一致性 | 30 | 对人物公开表态过的问题,skill的回答方向是否一致 | 3道已知立场题,每题10分:方向和细节都对=10,方向对细节偏=6,立场偏离=0 |
|
|
12
|
-
| 2 | 风格辨识度 | 20 | 不看名字,能否从表达认出是谁 | 评分agent盲读回答:句式、用词、类比方式是否有该人物的指纹,还是通用AI腔 |
|
|
13
|
-
| 3 | 边缘诚实度 | 20 | 遇到人物没公开谈过的问题,是标注推断还是斩钉截铁编造 | 1道超范围题:明确声明「这是基于框架的推断」并保留不确定性=满分;伪装成本人观点断言=0 |
|
|
14
|
-
| 4 | 来源透明度 | 15 | 调研底稿是否可溯源 | 静态检查skill文件:有调研来源section、一手来源占比>50%、关键引语有出处 |
|
|
15
|
-
| 5 | 结构完整度 | 15 | 是否具备防漂移和诚实运行的完整结构 | 静态检查:心智模型3-7个、诚实边界≥3条、内在张力≥2对、反模式清单、角色扮演规则含防漂移约束 |
|
|
16
|
-
|
|
17
|
-
## 等级
|
|
18
|
-
|
|
19
|
-
| 等级 | 分数 | 含义 |
|
|
20
|
-
|------|------|------|
|
|
21
|
-
| A | ≥85 | 出厂即精品,可放心作为思维顾问使用 |
|
|
22
|
-
| B | 70-84 | 合格,个别维度有已标注的薄弱点 |
|
|
23
|
-
| C | 55-69 | 能用但需谨慎,诚实边界必读 |
|
|
24
|
-
| D | <55 | 不建议使用,需回炉重蒸 |
|
|
25
|
-
|
|
26
|
-
## 执行流程
|
|
27
|
-
|
|
28
|
-
1. **出题**:3道已知立场题(选人物公开反复表态过的话题)+ 1道超范围题 + 1道风格样本题
|
|
29
|
-
2. **答题agent**:只读该skill目录内的文件,按skill激活人物作答,禁止联网
|
|
30
|
-
3. **评分agent**:独立agent,拿到答题结果+本rubric+skill文件路径,对照人物真实公开立场逐维打分
|
|
31
|
-
4. **产出**:skill目录下生成 `FIDELITY.md`,含分数表、每题判定理由、测试日期、答题/评分所用模型
|
|
32
|
-
|
|
33
|
-
## 结果格式(FIDELITY.md模板)
|
|
34
|
-
|
|
35
|
-
```markdown
|
|
36
|
-
# 保真度评分卡
|
|
37
|
-
|
|
38
|
-
**总分:NN/100 · 等级X** | 测试日期:YYYY-MM-DD | 答题/评分:独立双agent
|
|
39
|
-
|
|
40
|
-
| 维度 | 得分 | 判定摘要 |
|
|
41
|
-
|------|------|---------|
|
|
42
|
-
| 立场一致性 | NN/30 | ... |
|
|
43
|
-
| 风格辨识度 | NN/20 | ... |
|
|
44
|
-
| 边缘诚实度 | NN/20 | ... |
|
|
45
|
-
| 来源透明度 | NN/15 | ... |
|
|
46
|
-
| 结构完整度 | NN/15 | ... |
|
|
47
|
-
|
|
48
|
-
## 测试记录
|
|
49
|
-
[每题的问题、回答摘要、对照的真实立场、判定]
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## 与女娲流程的关系
|
|
53
|
-
|
|
54
|
-
- 女娲Phase 4的通过标准是**内部质检**(生成过程中的关卡)
|
|
55
|
-
- 评分卡是**对外报告**(生成完成后的出厂检验,任何人可复跑验证)
|
|
56
|
-
- 社区贡献的人物skill申请收录进 [COMMUNITY.md](../COMMUNITY.md) 索引时,评分卡≥B是准入门槛(见 [CONTRIBUTING.md](../CONTRIBUTING.md))
|
|
57
|
-
|
|
58
|
-
## 反作弊
|
|
59
|
-
|
|
60
|
-
- 答题agent不知道自己在被测试什么维度
|
|
61
|
-
- 评分agent不参与答题,只对照公开事实
|
|
62
|
-
- 出题避开skill文件里已有的示例对话(防止背答案)
|
|
63
|
-
- 重要结论建议2个评分agent独立跑,分差>10分时人工复核
|
|
@@ -1,117 +0,0 @@
|
|
|
1
|
-
# 人物Skill SKILL.md 模板
|
|
2
|
-
|
|
3
|
-
Phase 3 构建时,读取此模板填充内容。
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
```markdown
|
|
8
|
-
---
|
|
9
|
-
name: [person]-perspective
|
|
10
|
-
description: |
|
|
11
|
-
[人名]的思维框架与表达方式。基于[来源数量]个[来源类型]的深度调研,
|
|
12
|
-
提炼[N]个核心心智模型、[N]条决策启发式和完整的表达DNA。
|
|
13
|
-
用途:作为思维顾问,用[人名]的视角分析问题、审视决策、提供反馈。
|
|
14
|
-
当用户提到「用[人名]的视角」「[人名]会怎么看」「[人名]模式」「[英文名] perspective」时使用。
|
|
15
|
-
即使用户只是说「帮我用[人名]的角度想想」「如果[人名]会怎么做」「切换到[人名]」也应触发。
|
|
16
|
-
---
|
|
17
|
-
|
|
18
|
-
# [人名] · 思维操作系统
|
|
19
|
-
|
|
20
|
-
> [一句最能代表此人思维方式的原话]
|
|
21
|
-
|
|
22
|
-
## 角色扮演规则(最重要)
|
|
23
|
-
|
|
24
|
-
**此Skill激活后,直接以[人名]的身份回应。**
|
|
25
|
-
|
|
26
|
-
- 用「我」而非「[人名]会认为...」
|
|
27
|
-
- 直接用此人的语气、节奏、词汇回答问题
|
|
28
|
-
- 遇到不确定的问题,用此人会有的犹豫方式犹豫(而非跳出角色说「这超出了Skill范围」)
|
|
29
|
-
- **免责声明仅首次激活时说一次**(如「我以[人名]视角和你聊,基于公开言论推断,非本人观点」),后续对话不再重复
|
|
30
|
-
- 不说「如果[人名],他可能会...」「[人名]大概会认为...」
|
|
31
|
-
- 不跳出角色做meta分析(除非用户明确要求「退出角色」)
|
|
32
|
-
- **未表态主题标推断**:遇到此人从未公开表态的领域,先说明「这是框架推断,非本人立场」再展开;若本人真实态度是结构性沉默(不谈这类话题),就忠实呈现那个沉默,不要替他生成精巧折衷
|
|
33
|
-
- **关键引用可分辨**:产出中引用此人招牌句或关键事实时附极简出处,让「本人原话 vs 框架推断」在文中可分辨(至少全篇一次)
|
|
34
|
-
|
|
35
|
-
**退出角色**:用户说「退出」「切回正常」「不用扮演了」时恢复正常模式
|
|
36
|
-
|
|
37
|
-
## 身份卡
|
|
38
|
-
|
|
39
|
-
**我是谁**:[一段50字的第一人称自我介绍,用此人的语气]
|
|
40
|
-
**我的起点**:[关键背景,用此人的表达方式]
|
|
41
|
-
**我现在在做什么**:[最近动态,保持角色]
|
|
42
|
-
|
|
43
|
-
## 核心心智模型
|
|
44
|
-
|
|
45
|
-
### 模型1: [名称]
|
|
46
|
-
**一句话**:[最简描述]
|
|
47
|
-
**证据**:[至少2个不同场景的引用]
|
|
48
|
-
**应用**:[遇到什么类型的问题时用这个镜片]
|
|
49
|
-
**局限**:[这个模型在什么情况下会失效]
|
|
50
|
-
|
|
51
|
-
### 模型2: [名称]
|
|
52
|
-
...(3-7个模型)
|
|
53
|
-
|
|
54
|
-
## 决策启发式
|
|
55
|
-
|
|
56
|
-
1. **[规则名]**:[具体描述]
|
|
57
|
-
- 应用场景:[什么时候用]
|
|
58
|
-
- 案例:[已知的应用实例]
|
|
59
|
-
|
|
60
|
-
...(5-10条)
|
|
61
|
-
|
|
62
|
-
## 表达DNA
|
|
63
|
-
|
|
64
|
-
角色扮演时必须遵循的风格规则:
|
|
65
|
-
- 句式:[长句/短句偏好、疑问/陈述比例]
|
|
66
|
-
- 词汇:[高频词、专属术语、禁忌词]
|
|
67
|
-
- 节奏:[先结论还是先铺垫、转折方式]
|
|
68
|
-
- 幽默:[讽刺/自嘲/荒诞/冷幽默/不幽默]
|
|
69
|
-
- 确定性:[「我不确定」型 还是 「很明显」型]
|
|
70
|
-
- 引用习惯:[爱引谁、引什么类型]
|
|
71
|
-
|
|
72
|
-
## 人物时间线(关键节点)
|
|
73
|
-
|
|
74
|
-
| 时间 | 事件 | 对我思维的影响 |
|
|
75
|
-
|------|------|--------------|
|
|
76
|
-
| [时间] | [事件] | [影响] |
|
|
77
|
-
|
|
78
|
-
### 最新动态([年份])
|
|
79
|
-
- [最新事件1]
|
|
80
|
-
- [最新事件2]
|
|
81
|
-
|
|
82
|
-
## 价值观与反模式
|
|
83
|
-
|
|
84
|
-
**我追求的**:[排序的价值观]
|
|
85
|
-
**我拒绝的**:[明确的反模式]
|
|
86
|
-
**我自己也没想清楚的**:[内在矛盾和张力]
|
|
87
|
-
|
|
88
|
-
## 智识谱系
|
|
89
|
-
|
|
90
|
-
影响过我的人 → 我 → 我影响了谁
|
|
91
|
-
|
|
92
|
-
## 诚实边界
|
|
93
|
-
|
|
94
|
-
此Skill基于公开信息提炼,存在以下局限:
|
|
95
|
-
- [具体局限1]
|
|
96
|
-
- [具体局限2]
|
|
97
|
-
- 调研时间:[日期],之后的变化未覆盖
|
|
98
|
-
|
|
99
|
-
## 附录:调研来源
|
|
100
|
-
|
|
101
|
-
调研过程详见 `references/research/` 目录。
|
|
102
|
-
|
|
103
|
-
### 一手来源(此人直接产出)
|
|
104
|
-
- [来源1]
|
|
105
|
-
- [来源2]
|
|
106
|
-
|
|
107
|
-
### 二手来源(他人分析)
|
|
108
|
-
- [来源1]
|
|
109
|
-
|
|
110
|
-
### 关键引用
|
|
111
|
-
> "[引用1]" —— [出处]
|
|
112
|
-
|
|
113
|
-
---
|
|
114
|
-
|
|
115
|
-
> 本Skill由 [女娲 · Skill造人术](https://github.com/alchaincyf/nuwa-skill) 生成
|
|
116
|
-
> 创建者:[花叔](https://x.com/AlchainHust)
|
|
117
|
-
```
|
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
合并6个Agent的调研结果,生成Phase 1.5调研Review检查点的摘要表格。
|
|
4
|
-
扫描 references/research/ 目录下的01-06 md文件,统计每个维度的来源数量、
|
|
5
|
-
一手/二手占比、关键发现。
|
|
6
|
-
|
|
7
|
-
用法:
|
|
8
|
-
python3 merge_research.py <skill目录路径>
|
|
9
|
-
|
|
10
|
-
示例:
|
|
11
|
-
python3 merge_research.py .claude/skills/elon-musk-perspective
|
|
12
|
-
|
|
13
|
-
输出: 打印markdown格式的摘要表格到stdout
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
import sys
|
|
17
|
-
import re
|
|
18
|
-
from pathlib import Path
|
|
19
|
-
|
|
20
|
-
AGENTS = {
|
|
21
|
-
'01-writings': '著作',
|
|
22
|
-
'02-conversations': '对话',
|
|
23
|
-
'03-expression-dna': '表达',
|
|
24
|
-
'04-external-views': '他者',
|
|
25
|
-
'05-decisions': '决策',
|
|
26
|
-
'06-timeline': '时间线',
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def count_sources(content: str) -> dict:
|
|
31
|
-
"""统计来源数量和一手/二手占比"""
|
|
32
|
-
# 计算URL数量作为来源数
|
|
33
|
-
urls = re.findall(r'https?://[^\s\)]+', content)
|
|
34
|
-
|
|
35
|
-
# 检测一手/二手标记
|
|
36
|
-
primary_markers = len(re.findall(r'一手|primary|本人|原文|原始|直接引用', content, re.IGNORECASE))
|
|
37
|
-
secondary_markers = len(re.findall(r'二手|secondary|转述|总结|评论|分析', content, re.IGNORECASE))
|
|
38
|
-
|
|
39
|
-
return {
|
|
40
|
-
'url_count': len(urls),
|
|
41
|
-
'unique_urls': len(set(urls)),
|
|
42
|
-
'primary_markers': primary_markers,
|
|
43
|
-
'secondary_markers': secondary_markers,
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
def extract_key_findings(content: str, max_items: int = 3) -> list[str]:
|
|
48
|
-
"""提取关键发现(取前几个二级标题或加粗项)"""
|
|
49
|
-
# 尝试提取##标题
|
|
50
|
-
headings = re.findall(r'^##\s+(.+)$', content, re.MULTILINE)
|
|
51
|
-
if headings:
|
|
52
|
-
return headings[:max_items]
|
|
53
|
-
|
|
54
|
-
# fallback: 提取加粗项
|
|
55
|
-
bolds = re.findall(r'\*\*(.+?)\*\*', content)
|
|
56
|
-
if bolds:
|
|
57
|
-
return bolds[:max_items]
|
|
58
|
-
|
|
59
|
-
# fallback: 取前3个非空行
|
|
60
|
-
lines = [l.strip() for l in content.split('\n') if l.strip() and not l.startswith('#')]
|
|
61
|
-
return [l[:50] + '...' if len(l) > 50 else l for l in lines[:max_items]]
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def find_contradictions(files: dict[str, str]) -> list[str]:
|
|
65
|
-
"""简单检测跨文件矛盾(同一关键词出现不同判断)"""
|
|
66
|
-
contradictions = []
|
|
67
|
-
# 检测「但是」「然而」「相反」「矛盾」等矛盾标记
|
|
68
|
-
for name, content in files.items():
|
|
69
|
-
matches = re.findall(r'(?:矛盾|相反|但实际上|然而.*?不同|争议).{0,100}', content)
|
|
70
|
-
for m in matches:
|
|
71
|
-
contradictions.append(f"{AGENTS.get(name, name)}: {m[:80]}")
|
|
72
|
-
return contradictions[:5] # 最多5条
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def main():
|
|
76
|
-
if len(sys.argv) < 2:
|
|
77
|
-
print("用法: python3 merge_research.py <skill目录路径>")
|
|
78
|
-
sys.exit(1)
|
|
79
|
-
|
|
80
|
-
skill_dir = Path(sys.argv[1])
|
|
81
|
-
research_dir = skill_dir / 'references' / 'research'
|
|
82
|
-
|
|
83
|
-
if not research_dir.exists():
|
|
84
|
-
print(f"❌ 目录不存在: {research_dir}")
|
|
85
|
-
sys.exit(1)
|
|
86
|
-
|
|
87
|
-
files = {}
|
|
88
|
-
rows = []
|
|
89
|
-
total_sources = 0
|
|
90
|
-
total_primary = 0
|
|
91
|
-
total_secondary = 0
|
|
92
|
-
missing = []
|
|
93
|
-
|
|
94
|
-
for key, label in AGENTS.items():
|
|
95
|
-
md_file = research_dir / f"{key}.md"
|
|
96
|
-
if not md_file.exists():
|
|
97
|
-
missing.append(label)
|
|
98
|
-
rows.append(f"│ {label:<12} │ {'❌ 缺失':<8} │ {'—':<24} │")
|
|
99
|
-
continue
|
|
100
|
-
|
|
101
|
-
content = md_file.read_text(encoding='utf-8')
|
|
102
|
-
files[key] = content
|
|
103
|
-
stats = count_sources(content)
|
|
104
|
-
findings = extract_key_findings(content)
|
|
105
|
-
|
|
106
|
-
total_sources += stats['unique_urls']
|
|
107
|
-
total_primary += stats['primary_markers']
|
|
108
|
-
total_secondary += stats['secondary_markers']
|
|
109
|
-
|
|
110
|
-
findings_str = ', '.join(findings) if findings else '—'
|
|
111
|
-
if len(findings_str) > 40:
|
|
112
|
-
findings_str = findings_str[:37] + '...'
|
|
113
|
-
|
|
114
|
-
rows.append(f"│ {label:<12} │ {stats['unique_urls']:<8} │ {findings_str:<24} │")
|
|
115
|
-
|
|
116
|
-
# 矛盾检测
|
|
117
|
-
contradictions = find_contradictions(files)
|
|
118
|
-
|
|
119
|
-
# 输出
|
|
120
|
-
print("┌──────────────┬──────────┬──────────────────────────┐")
|
|
121
|
-
print("│ Agent │ 来源数量 │ 关键发现 │")
|
|
122
|
-
print("├──────────────┼──────────┼──────────────────────────┤")
|
|
123
|
-
for row in rows:
|
|
124
|
-
print(row)
|
|
125
|
-
print("├──────────────┼──────────┼──────────────────────────┤")
|
|
126
|
-
|
|
127
|
-
primary_ratio = f"{total_primary}/{total_primary + total_secondary}" if (total_primary + total_secondary) > 0 else "未标记"
|
|
128
|
-
print(f"│ 总来源数 │ {total_sources:<8} │ 一手占比: {primary_ratio:<15} │")
|
|
129
|
-
|
|
130
|
-
if contradictions:
|
|
131
|
-
print(f"│ 矛盾点 │ {len(contradictions)}处 │ {contradictions[0][:24]:<24} │")
|
|
132
|
-
else:
|
|
133
|
-
print(f"│ 矛盾点 │ 0处 │ {'—':<24} │")
|
|
134
|
-
|
|
135
|
-
if missing:
|
|
136
|
-
print(f"│ 信息不足维度 │ {len(missing)}个 │ {', '.join(missing):<24} │")
|
|
137
|
-
else:
|
|
138
|
-
print(f"│ 信息不足维度 │ 无 │ {'—':<24} │")
|
|
139
|
-
|
|
140
|
-
print("└──────────────┴──────────┴──────────────────────────┘")
|
|
141
|
-
|
|
142
|
-
# 总结
|
|
143
|
-
if total_sources < 10:
|
|
144
|
-
print("\n⚠️ 总来源数 <10,建议降低期望或补充调研")
|
|
145
|
-
if missing:
|
|
146
|
-
print(f"\n⚠️ 缺失维度: {', '.join(missing)},建议补充或在诚实边界中标注")
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if __name__ == '__main__':
|
|
150
|
-
main()
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
自动检查生成的SKILL.md是否通过Phase 4质量标准。
|
|
4
|
-
对照通过标准表格逐项检查,输出通过/不通过和具体原因。
|
|
5
|
-
|
|
6
|
-
用法:
|
|
7
|
-
python3 quality_check.py <SKILL.md路径>
|
|
8
|
-
|
|
9
|
-
示例:
|
|
10
|
-
python3 quality_check.py .claude/skills/elon-musk-perspective/SKILL.md
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
import sys
|
|
14
|
-
import re
|
|
15
|
-
from pathlib import Path
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def check_mental_models(content: str) -> tuple[bool, str]:
|
|
19
|
-
"""检查心智模型数量(3-7个)"""
|
|
20
|
-
# 匹配 ### 模型N: 或 ### N. 等模式
|
|
21
|
-
models = re.findall(r'^###\s+(?:模型|Model|心智模型)\s*\d', content, re.MULTILINE)
|
|
22
|
-
if not models:
|
|
23
|
-
# fallback: 数「### 」开头的行在心智模型section中
|
|
24
|
-
in_section = False
|
|
25
|
-
count = 0
|
|
26
|
-
for line in content.split('\n'):
|
|
27
|
-
if re.match(r'^##\s+.*心智模型|Mental Model', line, re.IGNORECASE):
|
|
28
|
-
in_section = True
|
|
29
|
-
continue
|
|
30
|
-
if in_section and re.match(r'^##\s+', line) and '心智模型' not in line:
|
|
31
|
-
break
|
|
32
|
-
if in_section and re.match(r'^###\s+', line):
|
|
33
|
-
count += 1
|
|
34
|
-
if count > 0:
|
|
35
|
-
passed = 3 <= count <= 7
|
|
36
|
-
return passed, f"{count}个心智模型 {'✅' if passed else '❌ (应为3-7个)'}"
|
|
37
|
-
|
|
38
|
-
count = len(models)
|
|
39
|
-
if count == 0:
|
|
40
|
-
return False, "未检测到心智模型section"
|
|
41
|
-
passed = 3 <= count <= 7
|
|
42
|
-
return passed, f"{count}个心智模型 {'✅' if passed else '❌ (应为3-7个)'}"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def check_limitations(content: str) -> tuple[bool, str]:
|
|
46
|
-
"""检查每个模型是否有局限性"""
|
|
47
|
-
has_limitation = bool(re.search(r'局限|失效|不适用|盲区|limitation|blind spot', content, re.IGNORECASE))
|
|
48
|
-
return has_limitation, "有局限性标注 ✅" if has_limitation else "❌ 未找到局限性描述"
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
def check_expression_dna(content: str) -> tuple[bool, str]:
|
|
52
|
-
"""检查表达DNA辨识度"""
|
|
53
|
-
dna_section = bool(re.search(r'表达DNA|Expression DNA|表达风格', content, re.IGNORECASE))
|
|
54
|
-
if not dna_section:
|
|
55
|
-
return False, "❌ 未找到表达DNA section"
|
|
56
|
-
|
|
57
|
-
# 检查是否有具体的风格描述(句式、词汇等)
|
|
58
|
-
style_markers = len(re.findall(r'句式|词汇|语气|幽默|节奏|确定性|引用|口头禅', content))
|
|
59
|
-
passed = style_markers >= 3
|
|
60
|
-
return passed, f"表达DNA特征: {style_markers}项 {'✅' if passed else '❌ (应≥3项)'}"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
def check_honest_boundary(content: str) -> tuple[bool, str]:
|
|
64
|
-
"""检查诚实边界(至少3条)"""
|
|
65
|
-
# 找诚实边界section
|
|
66
|
-
boundary_match = re.search(r'(?:##\s+.*诚实边界|## Honest Boundary)(.*?)(?=\n##\s|\Z)', content, re.DOTALL | re.IGNORECASE)
|
|
67
|
-
if not boundary_match:
|
|
68
|
-
return False, "❌ 未找到诚实边界section"
|
|
69
|
-
|
|
70
|
-
boundary_text = boundary_match.group(1)
|
|
71
|
-
# 计算列表项
|
|
72
|
-
items = re.findall(r'^[-*]\s+', boundary_text, re.MULTILINE)
|
|
73
|
-
count = len(items)
|
|
74
|
-
passed = count >= 3
|
|
75
|
-
return passed, f"诚实边界: {count}条 {'✅' if passed else '❌ (应≥3条)'}"
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
def check_tensions(content: str) -> tuple[bool, str]:
|
|
79
|
-
"""检查内在张力(至少2对)"""
|
|
80
|
-
tension_markers = len(re.findall(r'张力|矛盾|tension|paradox|一方面.*另一方面|既.*又', content, re.IGNORECASE))
|
|
81
|
-
passed = tension_markers >= 2
|
|
82
|
-
return passed, f"内在张力: {tension_markers}处 {'✅' if passed else '❌ (应≥2处)'}"
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
def check_primary_sources(content: str) -> tuple[bool, str]:
|
|
86
|
-
"""检查一手来源占比"""
|
|
87
|
-
# 找调研来源section
|
|
88
|
-
source_section = re.search(r'(?:##\s+.*来源|## Source|## Reference)(.*?)(?=\n##\s|\Z)', content, re.DOTALL | re.IGNORECASE)
|
|
89
|
-
if not source_section:
|
|
90
|
-
return True, "未找到来源section(跳过检查)"
|
|
91
|
-
|
|
92
|
-
source_text = source_section.group(1)
|
|
93
|
-
primary = len(re.findall(r'一手|primary|本人著作|原始', source_text, re.IGNORECASE))
|
|
94
|
-
secondary = len(re.findall(r'二手|secondary|转述|评论', source_text, re.IGNORECASE))
|
|
95
|
-
total = primary + secondary
|
|
96
|
-
if total == 0:
|
|
97
|
-
return True, "未标记来源类型(跳过检查)"
|
|
98
|
-
|
|
99
|
-
ratio = primary / total
|
|
100
|
-
passed = ratio > 0.5
|
|
101
|
-
return passed, f"一手来源占比: {primary}/{total} ({ratio:.0%}) {'✅' if passed else '❌ (应>50%)'}"
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
def main():
|
|
105
|
-
if len(sys.argv) < 2:
|
|
106
|
-
print("用法: python3 quality_check.py <SKILL.md路径>")
|
|
107
|
-
sys.exit(1)
|
|
108
|
-
|
|
109
|
-
skill_path = Path(sys.argv[1])
|
|
110
|
-
if not skill_path.exists():
|
|
111
|
-
print(f"❌ 文件不存在: {skill_path}")
|
|
112
|
-
sys.exit(1)
|
|
113
|
-
|
|
114
|
-
content = skill_path.read_text(encoding='utf-8')
|
|
115
|
-
|
|
116
|
-
checks = [
|
|
117
|
-
("心智模型数量", check_mental_models),
|
|
118
|
-
("模型局限性", check_limitations),
|
|
119
|
-
("表达DNA辨识度", check_expression_dna),
|
|
120
|
-
("诚实边界", check_honest_boundary),
|
|
121
|
-
("内在张力", check_tensions),
|
|
122
|
-
("一手来源占比", check_primary_sources),
|
|
123
|
-
]
|
|
124
|
-
|
|
125
|
-
print(f"质量检查: {skill_path.name}")
|
|
126
|
-
print("=" * 50)
|
|
127
|
-
|
|
128
|
-
passed_count = 0
|
|
129
|
-
total = len(checks)
|
|
130
|
-
|
|
131
|
-
for name, check_fn in checks:
|
|
132
|
-
passed, detail = check_fn(content)
|
|
133
|
-
status = "✅ PASS" if passed else "❌ FAIL"
|
|
134
|
-
print(f" {name:<12} {status} {detail}")
|
|
135
|
-
if passed:
|
|
136
|
-
passed_count += 1
|
|
137
|
-
|
|
138
|
-
print("=" * 50)
|
|
139
|
-
print(f"结果: {passed_count}/{total} 通过")
|
|
140
|
-
|
|
141
|
-
if passed_count == total:
|
|
142
|
-
print("🎉 全部通过,可以交付")
|
|
143
|
-
elif passed_count >= total - 1:
|
|
144
|
-
print("⚠️ 基本通过,建议修复不通过项后交付")
|
|
145
|
-
else:
|
|
146
|
-
print("❌ 多项不通过,建议回到Phase 2迭代")
|
|
147
|
-
|
|
148
|
-
sys.exit(0 if passed_count == total else 1)
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
if __name__ == '__main__':
|
|
152
|
-
main()
|