@metago-ai/engine 2.1.2 → 2.1.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.
Files changed (67) hide show
  1. package/BOUNDARIES.md +109 -0
  2. package/CHANGES.md +4 -4
  3. package/CONSTITUTION/AXIOMS.md +72 -110
  4. package/CORE/ATOMS.md +611 -0
  5. package/CORE/ATTRIBUTES.md +70 -101
  6. package/CORE/PROTOCOLS.md +134 -116
  7. package/ENGINE.md +6 -6
  8. package/ENGINES/engine-runtime.cjs +318 -0
  9. package/ENGINES/final-engines-runtime.cjs +683 -0
  10. package/ENGINES/governance-runtime.cjs +582 -0
  11. package/ENGINES/math-capability-runtime.cjs +451 -0
  12. package/ENGINES/philosophy-runtime.cjs +427 -0
  13. package/ENGINES/yili/data/yaoci-1.js +24 -0
  14. package/ENGINES/yili/data/yaoci-2.js +21 -0
  15. package/ENGINES/yili/data/yaoci-3.js +21 -0
  16. package/ENGINES/yili/data/yaoci-4.js +21 -0
  17. package/ENGINES/yili/data/yaoci.js +17 -0
  18. package/ENGINES/yili/lib/almanac.js +416 -0
  19. package/ENGINES/yili/lib/bazi.js +127 -0
  20. package/ENGINES/yili/lib/diagnose.js +71 -0
  21. package/ENGINES/yili/lib/hetu-luoshu.js +123 -0
  22. package/ENGINES/yili/lib/index.js +23 -0
  23. package/ENGINES/yili/lib/liuyao.js +226 -0
  24. package/ENGINES/yili/lib/qimen.js +167 -0
  25. package/ENGINES/yili/lib/shushu-calculus.js +85 -0
  26. package/ENGINES/yili/lib/taiyi.js +83 -0
  27. package/ENGINES/yili/lib/vendor/shouxing-core.js +627 -0
  28. package/ENGINES/yili/lib/wuxing.js +106 -0
  29. package/ENGINES/yili/lib/yijing.js +226 -0
  30. package/ENGINES/yili/lib/zeri.js +80 -0
  31. package/ENGINES/yili/lib/ziwei.js +145 -0
  32. package/ENGINES/yili/package.json +1 -0
  33. package/EXECUTORS.md +85 -0
  34. package/GENOME.json +11 -10
  35. package/INDEX/ENGINES.md +168 -0
  36. package/INDEX/engines.json +161 -161
  37. package/INDEX/knowledge.json +2 -2
  38. package/INDEX/skills.json +29 -5
  39. package/INDEX/tools.json +64 -64
  40. package/PATENTS.md +1 -1
  41. package/PROTOCOLS/closure-runtime.cjs +288 -0
  42. package/PROTOCOLS/covenant-runtime.cjs +409 -0
  43. package/PROTOCOLS/final-runtime.cjs +680 -0
  44. package/PROTOCOLS/formula-runtime.cjs +399 -0
  45. package/PROTOCOLS/proactive-runtime.cjs +368 -0
  46. package/PROTOCOLS/rule-runtime.cjs +448 -0
  47. package/PROTOCOLS/runtime.cjs +441 -0
  48. package/README.md +5 -5
  49. package/RUNTIME/dist/kmwi-memory.d.ts.map +1 -1
  50. package/RUNTIME/dist/kmwi-memory.js +14 -2
  51. package/RUNTIME/dist/kmwi-memory.js.map +1 -1
  52. package/RUNTIME/dist/validators.d.ts +2 -2
  53. package/RUNTIME/dist/validators.js +19 -10
  54. package/atoms/approx.cjs +293 -0
  55. package/atoms/atom-factory.cjs +550 -0
  56. package/atoms/atoms-cosmic-bio.cjs +340 -0
  57. package/atoms/atoms-crypto-emotion.cjs +215 -0
  58. package/atoms/atoms_engines.json +5821 -0
  59. package/atoms/blueprint-atoms-2.cjs +583 -0
  60. package/atoms/blueprint-atoms.cjs +975 -0
  61. package/atoms/constraints.cjs +257 -0
  62. package/atoms/contract-validator.cjs +213 -0
  63. package/atoms/engine.cjs +849 -0
  64. package/atoms/specialized.cjs +530 -0
  65. package/atoms/verify.cjs +94 -0
  66. package/package.json +97 -91
  67. package/scripts/verify-dist.cjs +80 -0
@@ -0,0 +1,583 @@
1
+ // blueprint-atoms-2.cjs — 第二批:把「需模型/需硬件」里能确定性实现的部分做掉
2
+ //
3
+ // 为什么能有第二批:
4
+ // 上一轮我把「契约产物是自然语言」直接判成「需大模型」。这个判断太粗。
5
+ // 自然语言产物有多种确定性生成方式:
6
+ // · 抽取式摘要(词频/位置/TextRank 打分选原句)——不需要生成,只需要选择
7
+ // · 模板填充(结构化数据 + 句式模板)——产物是文本,但由数据决定
8
+ // · 规则库匹配(特征 → 预设策略)——产物的选择由规则决定
9
+ // · 术语表替换(专业词 → 通俗词 + 类比)——改写而非创作
10
+ // · 信号特征提取(HRV 时域/频域指标)——纯数学
11
+ //
12
+ // 纪律(不许造假):
13
+ // · 每条都必须有真实算法,产物由输入决定,不同输入必须给出不同产物
14
+ // · 做不到的(真需视觉模型/真需物理设备/真需训练好的解码器)继续诚实标注,不硬凑
15
+ 'use strict'
16
+
17
+ const r4 = x => { const v = Number(x); if (!isFinite(v)) return null; const s = v * 1e4; return isFinite(s) ? Math.round(s) / 1e4 : v }
18
+ const toArr = v => Array.isArray(v) ? v : (v === null || v === undefined ? [] : [v])
19
+ const toNum = v => { const n = Number(v); return isFinite(n) ? n : 0 }
20
+ const clamp01 = x => Math.max(0, Math.min(1, Number(x) || 0))
21
+
22
+ // ── 中文分句 / 分词(无依赖,用于摘要与关键词)────────────
23
+ function splitSentences(text) {
24
+ return String(text || '')
25
+ .split(/(?<=[。!?;\n])/g)
26
+ .map(s => s.trim())
27
+ .filter(s => s.length > 0)
28
+ }
29
+ function tokenize(text) {
30
+ const t = String(text || '')
31
+ const cjk = t.match(/[\u4e00-\u9fa5]{2,4}/g) || []
32
+ const en = (t.toLowerCase().match(/[a-z][a-z0-9\-]{2,}/g) || [])
33
+ const num = t.match(/\d+(?:\.\d+)?%?/g) || []
34
+ return [...cjk, ...en, ...num]
35
+ }
36
+
37
+ // ══════════════════════════════════════════════════════════════
38
+ // 1. 时事摘要生成(ATOM_NEWS_SUMMARY_304):抽取式摘要
39
+ // 算法:词频 × 位置权重 × 长度惩罚 → 选 top-N 原句按原序拼接
40
+ // ══════════════════════════════════════════════════════════════
41
+ function newsSummary(input) {
42
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { text: String(input || '') }
43
+ const text = String(o.text || o.news || o.article || o.content || (typeof input === 'string' ? input : ''))
44
+ if (!text.trim()) return { ok: false, success: false, reason: 'EMPTY_TEXT', message: '缺少待摘要文本' }
45
+ const sents = splitSentences(text)
46
+ if (!sents.length) return { ok: false, success: false, reason: 'NO_SENTENCE', message: '无法分句' }
47
+
48
+ // 词频表(去停用词)
49
+ const STOP = new Set(['我们', '他们', '这个', '那个', '可以', '已经', '表示', '进行', '通过', '以及', '但是', '因为', '所以', '如果', '并且', '或者', '目前', '同时', '此外'])
50
+ const tf = {}
51
+ for (const s of sents) for (const w of tokenize(s)) { if (!STOP.has(w)) tf[w] = (tf[w] || 0) + 1 }
52
+
53
+ // 每句打分:词频均值 × 位置权重(首尾句加权)× 长度惩罚
54
+ const scored = sents.map((s, i) => {
55
+ const ws = tokenize(s).filter(w => !STOP.has(w))
56
+ const freq = ws.length ? ws.reduce((a, w) => a + (tf[w] || 0), 0) / ws.length : 0
57
+ const posW = i === 0 ? 1.3 : (i === sents.length - 1 ? 1.15 : 1.0)
58
+ const lenPenalty = s.length > 120 ? 0.85 : (s.length < 8 ? 0.6 : 1.0)
59
+ return { i, text: s, score: r4(freq * posW * lenPenalty), len: s.length }
60
+ })
61
+
62
+ const maxSent = Math.max(1, Math.min(toNum(o.maxSentences) || Math.ceil(sents.length * 0.35), 8))
63
+ const picked = scored.slice().sort((a, b) => b.score - a.score).slice(0, maxSent).sort((a, b) => a.i - b.i)
64
+
65
+ // 关键词:词频 top-8
66
+ const keywords = Object.keys(tf).sort((a, b) => tf[b] - tf[a]).slice(0, 8).map(w => ({ word: w, freq: tf[w] }))
67
+
68
+ const summary = picked.map(p => p.text).join('')
69
+ const ratio = r4(summary.length / Math.max(1, text.length))
70
+ return {
71
+ ok: true, success: true,
72
+ output: {
73
+ summary, summaryLength: summary.length, originalLength: text.length, ratio,
74
+ sentenceCount: sents.length, pickedCount: picked.length,
75
+ picked: picked.map(p => ({ index: p.i, score: p.score, text: p.text })),
76
+ keywords,
77
+ method: 'extractive-tf-pos',
78
+ },
79
+ provenance: ['[BP2_ATOM_NEWS_SUMMARY_304] 抽取式摘要:词频×位置权重×长度惩罚,选句不生成'],
80
+ }
81
+ }
82
+
83
+ // ══════════════════════════════════════════════════════════════
84
+ // 2. 政策翻译官(ATOM_POLICY_TRANSLATE_101):术语表替换 + 句式通俗化
85
+ // ══════════════════════════════════════════════════════════════
86
+ const POLICY_TERMS = [
87
+ [['普惠性', '普惠'], '覆盖面广、大家都够得着'],
88
+ [['专项', '专项资金'], '为某件事单独拨的钱'],
89
+ [['申报'], '提交申请'],
90
+ [['核准', '核定'], '官方审核后确定'],
91
+ [['备案'], '登记留档'],
92
+ [['补贴'], '政府给的钱'],
93
+ [['税收减免', '减免税'], '少交税'],
94
+ [['贴息'], '政府帮你付一部分利息'],
95
+ [['配套资金'], '要求你自筹一部分钱'],
96
+ [['门槛'], '最低条件'],
97
+ [['资质'], '官方认可的资格'],
98
+ [['兑现'], '把钱或政策落到实处'],
99
+ [['实施细则'], '具体怎么操作的规定'],
100
+ [['有效期内'], '在规定时间内'],
101
+ [['主体'], '申请人或单位'],
102
+ [['统筹'], '统一安排'],
103
+ [['试点'], '先在小范围试'],
104
+ [['梯度'], '分档次'],
105
+ [['动态调整'], '会随情况变化'],
106
+ [['一事一议'], '每一件单独商量'],
107
+ ]
108
+ function policyTranslate(input) {
109
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { text: String(input || '') }
110
+ const raw = String(o.text || o.policy || o.content || (typeof input === 'string' ? input : ''))
111
+ if (!raw.trim()) return { ok: false, success: false, reason: 'EMPTY_TEXT', message: '缺少政策原文' }
112
+
113
+ /* 方案:**括号注释**,不重写句子。
114
+ 理由:纯规则改写做不到通顺(它不懂语法),强行替换只会产出「词对但句错」的乱码。
115
+ 保留原文结构、在术语后加括号解释,既通顺又不丢信息——这才是真实可用的产物。 */
116
+ const applied = []
117
+ let annotated = raw
118
+ for (const [keys, rep] of POLICY_TERMS) {
119
+ for (const k of keys) {
120
+ if (annotated.indexOf(k) < 0) continue
121
+ // 避免重复注释(该术语已被括注过)
122
+ const already = new RegExp(k + '([^)]*)').test(annotated)
123
+ if (!already) annotated = annotated.split(k).join(k + '(' + rep + ')')
124
+ applied.push({ term: k, plain: rep })
125
+ break
126
+ }
127
+ }
128
+ // 清理可能的嵌套括号与重复标点
129
+ annotated = annotated.replace(/(([^()]*))(([^()]*))/g, '($1)')
130
+ annotated = annotated.replace(/[。;]{2,}/g, '。')
131
+
132
+ // 分句(>55 字按逗号切,避免长句难读)
133
+ const sentences = splitSentences(annotated)
134
+ .flatMap(s => s.replace(/([^)]*)/g, '').length > 55 ? s.split(/[,,]/).map(x => x.trim()).filter(Boolean).map(x => x + '。') : [s])
135
+
136
+ // 硬信息(数字/期限/金额):单独抽出来,这些是不能改写的
137
+ const facts = (raw.match(/\d+(?:\.\d+)?\s*(?:%|万元|亿元|元|个工作日|天|月|年)/g) || [])
138
+
139
+ // 术语对照表(供用户逐条核对)
140
+ const table = applied.map(a => ({ 术语: a.term, 通俗: a.plain }))
141
+
142
+ return {
143
+ ok: true, success: true,
144
+ output: {
145
+ // 主产物:注释版原文(通顺、信息无损)
146
+ annotated,
147
+ // 副产物:术语对照表
148
+ glossary: table,
149
+ termCount: applied.length,
150
+ original: raw,
151
+ hardFacts: [...new Set(facts)],
152
+ sentenceCount: sentences.length,
153
+ // 能力边界:明确这是「加注」不是「重写」
154
+ method: 'inline-gloss',
155
+ note: '本实现给政策术语加括号注释,保留原文结构;不做整句重写(纯规则无法保证改写后通顺)。',
156
+ },
157
+ provenance: ['[BP2_ATOM_POLICY_TRANSLATE_101] 术语内联注释:保留原文 + 括号解释 + 术语对照表;硬信息不改写'],
158
+ }
159
+ }
160
+
161
+ // ══════════════════════════════════════════════════════════════
162
+ // 3. 科技祛魅器(ATOM_TECH_DEMYSTIFY_201):术语表 + 类比库
163
+ // ══════════════════════════════════════════════════════════════
164
+ const TECH_TERMS = [
165
+ [['大模型', 'LLM', '大语言模型'], '读过海量文字、学会接话茬的程序', '像一个读完全市图书馆、能跟你聊任何话题的人'],
166
+ [['神经网络'], '模仿脑细胞连接方式的计算结构', '像一张巨大的网,每个结都在传小纸条'],
167
+ [['训练'], '拿大量例子反复调整参数', '像反复做题对答案,慢慢摸出规律'],
168
+ [['推理'], '训练好之后用来回答问题', '像考场上用学到的东西答题'],
169
+ [['向量', 'embedding'], '把东西变成一串数字', '像给每样东西编一个坐标,意思近的坐标就挨得近'],
170
+ [['微调'], '在通用模型上再用专门数据调一遍', '像大学毕业后又上了个岗位培训班'],
171
+ [['RAG', '检索增强'], '先去资料库找答案再回答', '像开卷考试,先翻书再写'],
172
+ [['Agent', '智能体'], '能自己规划并动手做事的程序', '像不只是出主意,还真的替你去办'],
173
+ [['算力'], '计算能力,通常指 GPU 数量', '像厨房里的灶眼数,越多同时炒的菜越多'],
174
+ [['参数'], '模型内部可调的数值', '像收音机上密密麻麻的旋钮'],
175
+ [['token'], '文本被切成的最小单位', '像把句子切成积木块来数'],
176
+ [['对齐'], '让模型行为符合人的期望', '像给它立规矩、教它分寸'],
177
+ [['幻觉'], '模型编出看似合理但不存在的内容', '像记错了却讲得理直气壮'],
178
+ [['多模态'], '能同时处理文字图片声音等', '像不只看字,还能看图听声'],
179
+ ]
180
+ function techDemystify(input) {
181
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { term: String(input || '') }
182
+ const term = String(o.term || o.text || o.name || (typeof input === 'string' ? input : ''))
183
+ if (!term.trim()) return { ok: false, success: false, reason: 'EMPTY_TERM', message: '缺少待解释术语' }
184
+ const hits = []
185
+ for (const [keys, what, analogy] of TECH_TERMS) {
186
+ if (keys.some(k => term.indexOf(k) >= 0 || k.toLowerCase() === term.toLowerCase())) {
187
+ hits.push({ term: keys[0], what, analogy })
188
+ }
189
+ }
190
+ const plain = hits.length
191
+ ? hits.map(h => `「${h.term}」就是${h.what}。${h.analogy}。`).join('')
192
+ : `「${term}」未在内置术语库中。已知 ${TECH_TERMS.length} 个术语,可尝试其中的一个。`
193
+ return {
194
+ ok: true, success: true,
195
+ output: { term, plain, matched: hits, matchedCount: hits.length, librarySize: TECH_TERMS.length, method: 'term-analogy-table' },
196
+ provenance: ['[BP2_ATOM_TECH_DEMYSTIFY_201] 术语表 + 类比库;未命中时明确告知而不是编造'],
197
+ }
198
+ }
199
+
200
+ // ══════════════════════════════════════════════════════════════
201
+ // 4. 思想见证器(ATOM_RES_IDEA_WITNESS_059):事件序列 → 结构化传记
202
+ // ══════════════════════════════════════════════════════════════
203
+ function ideaWitness(input) {
204
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { events: toArr(input) }
205
+ const events = toArr(o.events || o.timeline || o.process || o.actions)
206
+ if (!events.length) return { ok: false, success: false, reason: 'NO_EVENTS', message: '缺少创意过程事件' }
207
+ const norm = events.map((e, i) => {
208
+ if (typeof e === 'string') return { index: i, stage: '事件', content: e, at: null }
209
+ return {
210
+ index: i,
211
+ stage: String((e && (e.stage || e.phase || e.type)) || '事件'),
212
+ content: String((e && (e.content || e.text || e.note || e.what)) || JSON.stringify(e)),
213
+ at: (e && (e.at || e.time || e.timestamp)) || null,
214
+ }
215
+ })
216
+ // 按阶段聚类,形成"传记"结构
217
+ const stages = {}
218
+ for (const n of norm) (stages[n.stage] = stages[n.stage] || []).push(n)
219
+ const chapterNames = Object.keys(stages)
220
+ const chapters = chapterNames.map((name, i) => ({
221
+ chapter: i + 1, name,
222
+ events: stages[name],
223
+ summary: `${name}阶段共 ${stages[name].length} 次记录:` + stages[name].slice(0, 3).map(x => x.content.slice(0, 24)).join(';'),
224
+ }))
225
+ // 传记正文(模板填充,内容由事件决定)
226
+ const bio = chapters.map(c => `第${c.chapter}章 ${c.name}\n${c.summary}`).join('\n\n')
227
+ // 提取转折点(阶段切换处)
228
+ const turns = []
229
+ for (let i = 1; i < norm.length; i++) if (norm[i].stage !== norm[i - 1].stage) turns.push({ at: norm[i].index, from: norm[i - 1].stage, to: norm[i].stage })
230
+ return {
231
+ ok: true, success: true,
232
+ output: {
233
+ biography: bio, chapters, chapterCount: chapters.length,
234
+ eventCount: norm.length, turningPoints: turns,
235
+ span: norm.length > 1 ? `${norm[0].index} → ${norm[norm.length - 1].index}` : '单事件',
236
+ method: 'event-cluster-template',
237
+ },
238
+ provenance: ['[BP2_ATOM_RES_IDEA_WITNESS_059] 事件按阶段聚类 → 模板化传记;正文由事件内容决定,不是固定文本'],
239
+ }
240
+ }
241
+
242
+ // ══════════════════════════════════════════════════════════════
243
+ // 5. 非技术转化器(ATOM_RES_NON_TECH_058):模式映射 → 结构化方案
244
+ // ══════════════════════════════════════════════════════════════
245
+ const NON_TECH_PATTERNS = [
246
+ { key: /太麻烦|太慢|等待|排队|手工|重复/, domain: '流程自动化', tech: ['任务编排', 'RPA', '批处理'], skeleton: ['识别重复步骤', '定义输入输出', '串成流水线', '加人工复核点'] },
247
+ { key: /记不住|找不到|忘了|乱|分散|版本/, domain: '知识管理', tech: ['结构化存储', '全文检索', '版本控制'], skeleton: ['统一入口', '建立索引', '按语义检索', '留痕与回溯'] },
248
+ { key: /沟通|协调|对齐|误解|信息不对称/, domain: '协同系统', tech: ['统一状态源', '变更通知', '权限分层'], skeleton: ['统一数据源', '事件驱动通知', '冲突检测', '责任归属'] },
249
+ { key: /算不清|统计|报表|核对|数据/, domain: '数据管道', tech: ['ETL', '指标口径', '自动校验'], skeleton: ['统一口径', '采集清洗', '计算指标', '异常告警'] },
250
+ { key: /质量|出错|返工|检查/, domain: '质量门禁', tech: ['自动化校验', '测试基线', '门禁阻断'], skeleton: ['定义验收判据', '自动化检查', '不通过即阻断', '回归对比'] },
251
+ { key: /客户|用户|反馈|需求/, domain: '需求管理', tech: ['反馈归集', '优先级评分', '闭环追踪'], skeleton: ['统一收集', '结构化打标', '加权排序', '闭环验证'] },
252
+ ]
253
+ function nonTechTransform(input) {
254
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { idea: String(input || '') }
255
+ const idea = String(o.idea || o.text || o.problem || (typeof input === 'string' ? input : ''))
256
+ if (!idea.trim()) return { ok: false, success: false, reason: 'EMPTY_IDEA', message: '缺少待转化想法' }
257
+ const hits = NON_TECH_PATTERNS.filter(p => p.key.test(idea))
258
+ const chosen = hits.length ? hits : [NON_TECH_PATTERNS[0]]
259
+ const plans = chosen.map((p, i) => ({
260
+ plan: i + 1, domain: p.domain,
261
+ candidateTech: p.tech,
262
+ steps: p.skeleton.map((s, j) => ({ step: j + 1, action: s })),
263
+ // 可行性:命中越多关键词越确定
264
+ confidence: r4(Math.min(1, (p.key.test(idea) ? 0.6 : 0.3) + (chosen.length === 1 ? 0.3 : 0.1))),
265
+ }))
266
+ return {
267
+ ok: true, success: true,
268
+ output: { idea, plans, planCount: plans.length, matchedPatterns: hits.length, librarySize: NON_TECH_PATTERNS.length, method: 'pattern-to-plan' },
269
+ provenance: ['[BP2_ATOM_RES_NON_TECH_058] 问题特征匹配 → 领域 + 技术候选 + 步骤骨架;未命中时给最通用域并标低置信'],
270
+ }
271
+ }
272
+
273
+ // ══════════════════════════════════════════════════════════════
274
+ // 6. 摩擦致敬器(ATOM_RES_FRICTION_061):痛苦表达 → 创造力路径
275
+ // ══════════════════════════════════════════════════════════════
276
+ const FRICTION_RULES = [
277
+ { key: /重复|枯燥|机械|没意思/, path: '把重复抽象成模板/工具', lever: '自动化', quote: '摩擦点=可自动化的边界' },
278
+ { key: /不会|不懂|学不会|难/, path: '把难点拆成最小可学单元', lever: '拆解', quote: '卡住的地方=知识缺口的位置' },
279
+ { key: /没人理解|说不清|沟通/, path: '把隐性经验显性化', lever: '形式化', quote: '说不清=还没想清' },
280
+ { key: /时间不够|来不及|太忙/, path: '找出真正的瓶颈环节', lever: '最小干预', quote: '忙=优先级没排完' },
281
+ { key: /做不完|太多|撑不住/, path: '按价值/成本二维筛选', lever: '取舍', quote: '做不完=该砍的没砍' },
282
+ { key: /失败|错|返工|白做/, path: '把失败转成可复用的检查项', lever: '沉淀', quote: '每次返工都是一条没写下的规则' },
283
+ { key: /不公平|凭什么|委屈/, path: '把隐含规则写成显式规则', lever: '显式化', quote: '不公平感=规则不透明的信号' },
284
+ { key: /孤独|没人|一个人/, path: '找同类问题的人共建', lever: '耦生', quote: '孤独=还没找到共振频率' },
285
+ ]
286
+ function frictionTribute(input) {
287
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { text: String(input || '') }
288
+ const text = String(o.text || o.pain || o.content || (typeof input === 'string' ? input : ''))
289
+ if (!text.trim()) return { ok: false, success: false, reason: 'EMPTY_TEXT', message: '缺少痛苦表达' }
290
+ const hits = FRICTION_RULES.filter(r => r.key.test(text))
291
+ const paths = (hits.length ? hits : [FRICTION_RULES[1]]).map((r, i) => ({
292
+ path: i + 1, trigger: text.match(r.key)?.[0] || r.key.source,
293
+ creativePath: r.path, lever: r.lever, insight: r.quote,
294
+ }))
295
+ return {
296
+ ok: true, success: true,
297
+ output: {
298
+ paths, pathCount: paths.length, matchedRules: hits.length, librarySize: FRICTION_RULES.length,
299
+ // 强度:命中规则数越多,说明这个痛苦越"结构化",越可转化
300
+ transformability: r4(clamp01(hits.length / 3)),
301
+ method: 'friction-rule-library',
302
+ },
303
+ provenance: ['[BP2_ATOM_RES_FRICTION_061] 痛苦表达特征 → 创造力路径规则库;可转化度=命中规则数/3'],
304
+ }
305
+ }
306
+
307
+ // ══════════════════════════════════════════════════════════════
308
+ // 7. 道在日常显现器(ATOM_FUSION_TAO_DAILY_043):场景 → 道之提示
309
+ // ══════════════════════════════════════════════════════════════
310
+ const TAO_SCENES = [
311
+ { key: /水|流|柔|退让/, hint: '水不争而利万物——以退为进,绕开硬处', principle: '柔弱胜刚强' },
312
+ { key: /谷|空|虚|留白|空杯/, hint: '谷因其空而能容——留出空白才有余地', principle: '虚室生白' },
313
+ { key: /生长|发芽|养|慢/, hint: '揠苗助长不如静待其时——生长有其节律', principle: '无为而无不为' },
314
+ { key: /反复|循环|周而复始|四季/, hint: '反者道之动——循环不是重复,是螺旋上升', principle: '反者道之动' },
315
+ { key: /刚|硬|强|对抗/, hint: '刚易折,柔常存——过刚处往往先断', principle: '守柔曰强' },
316
+ { key: /少|简|减|舍/, hint: '为学日益,为道日损——减去多余的才见本质', principle: '损之又损' },
317
+ { key: /静|定|安|沉/, hint: '静为躁君——先静下来,躁动自息', principle: '致虚极,守静笃' },
318
+ { key: /知足|满|贪|多/, hint: '知足不辱,知止不殆——知道停的人才走得远', principle: '知止不殆' },
319
+ { key: /始|终|成|败/, hint: '慎终如始,则无败事——收尾时仍如开头般谨慎', principle: '慎终如始' },
320
+ { key: /大|巨|宏|远/, hint: '天下大事必作于细——再大的事也从最小处起', principle: '图难于其易' },
321
+ ]
322
+ function taoDaily(input) {
323
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { scene: String(input || '') }
324
+ const scene = String(o.scene || o.text || o.content || (typeof input === 'string' ? input : ''))
325
+ if (!scene.trim()) return { ok: false, success: false, reason: 'EMPTY_SCENE', message: '缺少日常场景' }
326
+ const hits = TAO_SCENES.filter(s => s.key.test(scene))
327
+ const hints = (hits.length ? hits : [TAO_SCENES[5]]).map((s, i) => ({
328
+ index: i + 1, scene: scene.match(s.key)?.[0] || '', hint: s.hint, principle: s.principle,
329
+ }))
330
+ return {
331
+ ok: true, success: true,
332
+ output: {
333
+ scene, hints, hintCount: hints.length, matchedScenes: hits.length, librarySize: TAO_SCENES.length,
334
+ // 只给提示,不做吉凶断言(避免超出可验证范围)
335
+ disclaimer: '提示为经典文本的场景映射,不构成对现实结果的预测',
336
+ method: 'scene-to-classic',
337
+ },
338
+ provenance: ['[BP2_ATOM_FUSION_TAO_DAILY_043] 场景特征 → 经典文本提示;仅映射不预测'],
339
+ }
340
+ }
341
+
342
+ // ══════════════════════════════════════════════════════════════
343
+ // 8. 负熵责任器(ATOM_RES_NEGENTROPY_066):指标 → 结构化负熵报告
344
+ // ══════════════════════════════════════════════════════════════
345
+ function negentropyReport(input) {
346
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { values: toArr(input) }
347
+ const vals = toArr(o.values || o.series || o.state || o.metrics).map(toNum).filter(v => isFinite(v))
348
+ if (vals.length < 2) return { ok: false, success: false, reason: 'TOO_FEW_VALUES', message: '至少需要 2 个数值' }
349
+ // Shannon 熵(归一化到 [0,1])
350
+ const sum = vals.reduce((a, b) => a + Math.abs(b), 0) || 1
351
+ const ps = vals.map(v => Math.abs(v) / sum)
352
+ const H = -ps.reduce((a, p) => a + (p > 0 ? p * Math.log(p) : 0), 0)
353
+ const Hmax = Math.log(vals.length)
354
+ const normalized = Hmax ? r4(H / Hmax) : 0
355
+ // 负熵 = 1 - 归一化熵(越有序越高)
356
+ const negentropy = r4(1 - (normalized || 0))
357
+ // 趋势:线性回归斜率
358
+ const xs = vals.map((_, i) => i)
359
+ const mx = xs.reduce((a, b) => a + b, 0) / xs.length
360
+ const my = vals.reduce((a, b) => a + b, 0) / vals.length
361
+ let num = 0, den = 0
362
+ for (let i = 0; i < vals.length; i++) { num += (xs[i] - mx) * (vals[i] - my); den += (xs[i] - mx) ** 2 }
363
+ const slope = den ? r4(num / den) : 0
364
+ const mean = r4(my)
365
+ const sd = r4(Math.sqrt(vals.reduce((a, v) => a + (v - my) ** 2, 0) / Math.max(1, vals.length - 1)))
366
+
367
+ const level = negentropy >= 0.7 ? '高度有序' : negentropy >= 0.4 ? '中等有序' : negentropy >= 0.2 ? '偏低有序' : '接近均质(高熵)'
368
+ const trendWord = Math.abs(slope) < 0.01 * (Math.abs(mean) || 1) ? '平稳' : (slope > 0 ? '上升' : '下降')
369
+ // 报告正文(模板填充,数据决定)
370
+ const report = [
371
+ `负熵评估:${level}(负熵 ${negentropy},归一化熵 ${normalized})`,
372
+ `样本 ${vals.length} 点,均值 ${mean},标准差 ${sd},趋势${trendWord}(斜率 ${slope})`,
373
+ negentropy < 0.4 ? '建议:结构过于均质,考虑引入分层/分类以提升有序度' : '结构有序度可维持,注意防止长期单极化',
374
+ ].join(';')
375
+ return {
376
+ ok: true, success: true,
377
+ output: {
378
+ report, level, negentropy, normalizedEntropy: normalized, entropy: r4(H), maxEntropy: r4(Hmax),
379
+ mean, sd, slope, trend: trendWord, count: vals.length,
380
+ // 对社会的有序度贡献:负熵为正即贡献为正
381
+ societalContribution: negentropy > 0.5 ? '正' : (negentropy > 0.2 ? '中性偏正' : '需改善'),
382
+ method: 'shannon-negentropy-report',
383
+ },
384
+ provenance: ['[BP2_ATOM_RES_NEGENTROPY_066] Shannon 熵 → 负熵 + 趋势 + 模板化报告;正文由数据决定'],
385
+ }
386
+ }
387
+
388
+ // ══════════════════════════════════════════════════════════════
389
+ // 9. 生理信号解码器(ATOM_PEOPLE_BIO_006):HRV/EDA 时域频域特征
390
+ // 契约写「脑电/心率/皮电 → 意图特征」。脑电需训练模型,但
391
+ // **心率变异性(HRV)与皮电(EDA)的时域/频域特征是纯数学**,可以真做。
392
+ // 对脑电输入:只做通用时序特征(均值/方差/频谱质心),明确标注"未做意图语义解码"。
393
+ // ══════════════════════════════════════════════════════════════
394
+ function bioDecode(input) {
395
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { signal: toArr(input) }
396
+ const raw = toArr(o.rr || o.hr || o.signal || o.samples || o.data).map(toNum).filter(v => isFinite(v) && v !== 0)
397
+ if (raw.length < 4) return { ok: false, success: false, reason: 'SIGNAL_TOO_SHORT', message: '至少需要 4 个采样点' }
398
+ const kind = String(o.kind || o.type || 'hr').toLowerCase()
399
+ const n = raw.length
400
+ const mean = raw.reduce((a, b) => a + b, 0) / n
401
+ const sd = Math.sqrt(raw.reduce((a, v) => a + (v - mean) ** 2, 0) / Math.max(1, n - 1))
402
+ // 相邻差分的均方根(RMSSD)—— HRV 核心时域指标
403
+ let sq = 0
404
+ for (let i = 1; i < n; i++) sq += (raw[i] - raw[i - 1]) ** 2
405
+ const rmssd = Math.sqrt(sq / Math.max(1, n - 1))
406
+ // pNN50 等价:相邻差值超过 mean*0.05 的比例
407
+ let cnt = 0
408
+ for (let i = 1; i < n; i++) if (Math.abs(raw[i] - raw[i - 1]) > mean * 0.05) cnt++
409
+ const pnn = r4(cnt / Math.max(1, n - 1))
410
+ // 频谱质心(简化 DFT 幅度加权)
411
+ let num = 0, den = 0
412
+ const K = Math.min(16, Math.floor(n / 2))
413
+ for (let k = 1; k <= K; k++) {
414
+ let re = 0, im = 0
415
+ for (let t = 0; t < n; t++) { const ang = 2 * Math.PI * k * t / n; re += raw[t] * Math.cos(ang); im -= raw[t] * Math.sin(ang) }
416
+ const mag = Math.sqrt(re * re + im * im)
417
+ num += k * mag; den += mag
418
+ }
419
+ const centroid = den ? r4(num / den) : 0
420
+ // LF/HF 近似(低频 k∈[1,3],高频 k∈[4,K])
421
+ const band = (lo, hi) => {
422
+ let s = 0
423
+ for (let k = lo; k <= Math.min(hi, K); k++) {
424
+ let re = 0, im = 0
425
+ for (let t = 0; t < n; t++) { const ang = 2 * Math.PI * k * t / n; re += raw[t] * Math.cos(ang); im -= raw[t] * Math.sin(ang) }
426
+ s += re * re + im * im
427
+ }
428
+ return s
429
+ }
430
+ const lf = band(1, 3), hf = band(4, K)
431
+ const lfhf = hf > 0 ? r4(lf / hf) : null
432
+ // 唤醒度代理:RMSSD 越低、LF/HF 越高 → 越偏交感激活
433
+ const arousal = r4(clamp01(0.5 + (lfhf !== null ? (lfhf - 1) * 0.25 : 0) - (rmssd / (mean || 1)) * 0.3))
434
+ const stress = arousal >= 0.65 ? '偏高' : arousal >= 0.45 ? '中等' : '偏低'
435
+ return {
436
+ ok: true, success: true,
437
+ output: {
438
+ kind,
439
+ features: { mean: r4(mean), sd: r4(sd), rmssd: r4(rmssd), pnn50Equiv: pnn, spectralCentroid: centroid, lfHfRatio: lfhf, arousal, stressLevel: stress },
440
+ // 明确能力边界:只做信号特征,不做意图语义解码
441
+ intentDecoded: false,
442
+ note: '本实现输出 HRV/EDA 时域频域特征与唤醒度代理;未做脑电意图语义解码(需训练好的解码器)。' +
443
+ '对脑电输入仅给通用时序特征。',
444
+ sampleCount: n,
445
+ method: 'hrv-time-frequency',
446
+ },
447
+ provenance: ['[BP2_ATOM_PEOPLE_BIO_006] HRV 时域(RMSSD/pNN50)+ 频域(LF/HF/质心)+ 唤醒度代理;不做意图语义解码'],
448
+ }
449
+ }
450
+
451
+ // ══════════════════════════════════════════════════════════════
452
+ // 10. 想法捕获器(ATOM_PEOPLE_CAPTURE_001):文本/结构化 → 想法向量
453
+ // 契约写「语音/文字/表情/草图/生理信号 → 结构化想法向量」。
454
+ // 语音识别/图像识别做不到,但**文本/结构化 → 向量**是确定性可做的。
455
+ // ══════════════════════════════════════════════════════════════
456
+ function peopleCapture(input) {
457
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { text: String(input || '') }
458
+ const sources = []
459
+ const parts = []
460
+ for (const k of ['text', 'speech', 'emoji', 'sketch', 'bio']) {
461
+ if (o[k] !== undefined && o[k] !== null && o[k] !== '') { sources.push(k); parts.push(String(o[k])) }
462
+ }
463
+ if (typeof input === 'string') { sources.push('text'); parts.push(input) }
464
+ const merged = parts.join(' ')
465
+ if (!merged.trim()) return { ok: false, success: false, reason: 'NO_INPUT', message: '缺少任何可捕获的输入(text/speech/emoji/sketch/bio)' }
466
+ // 向量化:固定 16 维词袋哈希(确定性)
467
+ const DIM = 16
468
+ const vec = new Array(DIM).fill(0)
469
+ const toks = tokenize(merged)
470
+ for (const w of toks) {
471
+ let h = 0
472
+ for (let i = 0; i < w.length; i++) h = (h * 31 + w.charCodeAt(i)) >>> 0
473
+ vec[h % DIM] += 1
474
+ }
475
+ const norm = Math.sqrt(vec.reduce((a, v) => a + v * v, 0)) || 1
476
+ const normalized = vec.map(v => r4(v / norm))
477
+ // 结构信息
478
+ const emotionHints = (merged.match(/好|棒|赞|满意|喜欢|差|糟|烦|怕|急|担心/g) || [])
479
+ return {
480
+ ok: true, success: true,
481
+ output: {
482
+ ideaVector: normalized, dimension: DIM,
483
+ sourcesUsed: sources, sourceCount: sources.length,
484
+ tokenCount: toks.length, charCount: merged.length,
485
+ emotionHints: [...new Set(emotionHints)],
486
+ // 能力边界
487
+ unsupportedSources: ['audio-to-text(需语音识别)', 'image-to-sketch(需图像识别)'].filter(x => !sources.length || true).slice(0, 2),
488
+ method: 'text-bag-hash16',
489
+ },
490
+ provenance: ['[BP2_ATOM_PEOPLE_CAPTURE_001] 文本/结构化输入 → 16 维词袋哈希向量;语音/图像识别不做(需外部模型)'],
491
+ }
492
+ }
493
+
494
+ // ══════════════════════════════════════════════════════════════
495
+ // 11. 情绪识别器(ATOM_EMOTION_RECOG_502):文本情绪识别(能力子集)
496
+ // 契约写「面部/语音/生理 → 情绪标签」。视觉/语音做不到,
497
+ // 但**文本情绪识别**是确定性可做的(词典 + 否定/程度处理)。
498
+ // ══════════════════════════════════════════════════════════════
499
+ const EMOTION_LEX = {
500
+ joy: ['开心', '高兴', '满意', '喜欢', '棒', '赞', '优秀', '太好了', '愉快', '幸福', 'happy', 'great', 'good'],
501
+ sadness: ['难过', '伤心', '失望', '遗憾', '沮丧', '低落', 'sad', 'sorry'],
502
+ anger: ['生气', '愤怒', '气愤', '恼火', '讨厌', '可恶', 'angry', 'hate'],
503
+ fear: ['害怕', '担心', '焦虑', '紧张', '恐', '不安', 'afraid', 'worried'],
504
+ surprise: ['惊讶', '意外', '居然', '没想到', 'surprised', 'wow'],
505
+ disgust: ['恶心', '反感', '厌恶', 'disgusting'],
506
+ }
507
+ const NEGATORS = ['不', '没', '无', '别', '非', '未']
508
+ const INTENSIFIERS = ['非常', '特别', '极其', '十分', '太', '超级', '很']
509
+ function emotionRecog(input) {
510
+ const o = (input && typeof input === 'object' && !Array.isArray(input)) ? input : { text: String(input || '') }
511
+ const text = String(o.text || o.audioText || o.content || (typeof input === 'string' ? input : ''))
512
+ const hasVision = (o.face !== undefined || o.image !== undefined)
513
+ if (!text.trim() && !hasVision) {
514
+ return {
515
+ ok: false, success: false, reason: 'NO_TEXT_INPUT',
516
+ message: '本实现只支持文本情绪识别;面部/语音情绪识别需视觉/语音模型,未提供',
517
+ output: { supported: ['text'], unsupported: ['face', 'voice', 'physiology'] },
518
+ }
519
+ }
520
+ const scores = {}
521
+ const hits = []
522
+ for (const emo of Object.keys(EMOTION_LEX)) {
523
+ let s = 0
524
+ for (const w of EMOTION_LEX[emo]) {
525
+ let idx = text.indexOf(w)
526
+ while (idx >= 0) {
527
+ // 否定词检测(前 3 字内)
528
+ const before = text.slice(Math.max(0, idx - 3), idx)
529
+ const negated = NEGATORS.some(n => before.indexOf(n) >= 0)
530
+ // 程度词检测
531
+ const intensified = INTENSIFIERS.some(i => before.indexOf(i) >= 0)
532
+ s += (negated ? -1 : 1) * (intensified ? 1.5 : 1)
533
+ hits.push({ word: w, emotion: emo, negated, intensified })
534
+ idx = text.indexOf(w, idx + w.length)
535
+ }
536
+ }
537
+ scores[emo] = r4(Math.max(0, s))
538
+ }
539
+ const total = Object.values(scores).reduce((a, b) => a + b, 0)
540
+ const normalized = {}
541
+ for (const k of Object.keys(scores)) normalized[k] = total > 0 ? r4(scores[k] / total) : 0
542
+ const ranked = Object.keys(normalized).map(k => ({ emotion: k, score: normalized[k] })).sort((a, b) => b.score - a.score)
543
+ const top = ranked[0]
544
+ const state = total === 0 ? 'neutral' : top.emotion
545
+ return {
546
+ ok: true, success: true,
547
+ output: {
548
+ '情绪': state, emotionState: state,
549
+ confidence: total === 0 ? 0 : r4(top.score),
550
+ intensity: r4(clamp01(total / 3)),
551
+ scores: ranked,
552
+ lexiconHits: hits.slice(0, 12),
553
+ // 能力边界:明确只做文本
554
+ supportedModality: ['text'], unsupportedModality: ['face', 'voice', 'physiology'],
555
+ method: 'text-lexicon-negation-intensity',
556
+ },
557
+ provenance: ['[BP2_ATOM_EMOTION_RECOG_502] 文本情绪识别:词典 + 否定翻转 + 程度加权;面部/语音不做(需视觉/语音模型)'],
558
+ }
559
+ }
560
+
561
+ // ══════════════════════════════════════════════════════════════
562
+ module.exports = {
563
+ IMPL: {
564
+ ATOM_NEWS_SUMMARY_304: newsSummary,
565
+ ATOM_POLICY_TRANSLATE_101: policyTranslate,
566
+ ATOM_TECH_DEMYSTIFY_201: techDemystify,
567
+ ATOM_RES_IDEA_WITNESS_059: ideaWitness,
568
+ ATOM_RES_NON_TECH_058: nonTechTransform,
569
+ ATOM_RES_FRICTION_061: frictionTribute,
570
+ ATOM_FUSION_TAO_DAILY_043: taoDaily,
571
+ ATOM_RES_NEGENTROPY_066: negentropyReport,
572
+ ATOM_PEOPLE_BIO_006: bioDecode,
573
+ ATOM_PEOPLE_CAPTURE_001: peopleCapture,
574
+ ATOM_EMOTION_RECOG_502: emotionRecog,
575
+ },
576
+ count: 11,
577
+ // 仍做不到的 3 条(真需视觉模型/物理设备/训练好的解码器)
578
+ STILL_UNSUPPORTED: [
579
+ 'ATOM_SECURE_LOCK_201(需物理锁具接口,纯软件无法真正控制硬件)',
580
+ 'ATOM_ACCESSIBLE_SIGN_507(需手语视频理解模型)',
581
+ 'ATOM_BIO_NEURAL_021(需脑电意图解码器训练)',
582
+ ],
583
+ }