dsh-vibe-math 0.3.4 → 0.3.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 CHANGED
@@ -15,6 +15,24 @@
15
15
 
16
16
  ---
17
17
 
18
+ ## 🧩 架构图(v1 + v2)
19
+
20
+ > 静态架构图;完整流程说明见 [docs/架构图.md](docs/架构图.md);可编辑生成脚本:[v1](docs/generate_framework_diagram.py) / [v2](docs/generate_framework_diagram_v2.py)。
21
+
22
+ ### Vibe Math V1(经典流水线)
23
+
24
+ ![Vibe Math V1 架构图](示例图/框架图-v1.png)
25
+
26
+ **一句话流水线**:`qs.csv` → Brainstorm 拆方向 → 每方向一个 Solver 多轮迭代(卡死则 Derive 派生新方向)→ 输出拆成最小验证单元 → ≥3 个 Verifier 独立审查 → 辩论 → 裁决 → 通过晋升 `Verified/` → Decider 回写 `qs.csv`;全程状态落盘 `VibeMath_State/`,`resume` 断点续跑,`manual` 模式在派发/裁决/晋升处挂起人工决策。
27
+
28
+ ### Vibe Math V2(新架构 · 概率驱动)
29
+
30
+ ![Vibe Math V2 架构图](示例图/框架图-v2.png)
31
+
32
+ **一句话流水线**:`qs.json` 按优先级取问题 → Explorer 拆方向(全死路则重派生)→ 每方向一个 Solver 多轮迭代(引理进 `Propos/`、解法回 `qs.json`,概率均 <1)→ 调度器选 r(命题 / 命题+证明·证伪 / 问题+解法)派 ≥3 验证器独立审查→辩论→裁决 → 概率=1 自动收口(问题 solved、命题 1/0,优先级置 `never`);全程状态落盘,`resume` 断点续跑,`reportMode` 可 file/push/both 汇报。
33
+
34
+ ---
35
+
18
36
  ## ✨ 功能特色
19
37
 
20
38
  - **多代理自动求解**:主代理把问题交给调度器,调度器派发 brainstorm / solver / verifier / decider(v1)或 explorer / solver / verifier(v2)等子代理协同求解,**你无需逐节点手操**。
@@ -43,6 +61,7 @@ dsh plugin --profile <你的 profile> add github:ChongCyrus/Vibe-Mathematics
43
61
 
44
62
  安装时插件会自动把两个 preset 写入 `~/.dsh/.agent-presets/`:`vibe-math-v1/` 与 `vibe-math-v2/`。
45
63
  之后新建会话,预设选择器里选择 **Vibe Math**(v1)或 **Vibe Math V2**(v2)即可。
64
+ **升级包版本后重启 DSH,未手动改过的 preset 文件会自动更新到新版本**(细节见文末「v2」安装器说明)。
46
65
 
47
66
  ### 方式 B:作为 agent preset 手动安装
48
67
 
@@ -92,116 +111,6 @@ dsh plugin --profile <你的 profile> add github:ChongCyrus/Vibe-Mathematics
92
111
 
93
112
  ---
94
113
 
95
- ## 🧩 架构图 · v1(经典)
96
-
97
- > 静态 PNG 预览 + 可编辑 Mermaid 图源(GitHub 原生渲染);完整流程说明见 [docs/架构图.md](docs/架构图.md)。
98
-
99
- ![Vibe Math V1 架构图](示例图/框架图-v1.png)
100
-
101
- ```mermaid
102
- flowchart TB
103
- subgraph L1["👤 交互层"]
104
- U["😀 用户(自然语言)"]
105
- M["🤖 主代理(助手 + 汇报者)<br/>翻译需求 · 汇报进度 · 问答配置<br/>不求解 · 不调度"]
106
- end
107
-
108
- subgraph L2["⚙️ 调度层(插件代码)"]
109
- SCHED["调度器 Scheduler<br/>唯一文件写者<br/>读 qs.csv · 派发子代理 · 推进状态机"]
110
- end
111
-
112
- subgraph L3["🧠 子代理层(continuable 持久会话)"]
113
- BRAIN["🧭 Brainstorm<br/>拆解多个求解方向"]
114
- SOLV["✍️ Solver × N<br/>逐方向多轮迭代"]
115
- DERI["🔀 Derive<br/>死路时派生新方向"]
116
- VERI["🔬 Verifier × ≥3<br/>独立审查 → 辩论 → 裁决"]
117
- DECI["⚖️ Decider<br/>判定是否解决"]
118
- end
119
-
120
- subgraph L4["💾 数据层 · VibeMath/Projects/&lt;项目&gt;/"]
121
- QS["📋 qs.csv"]
122
- PEND["📥 Pending_Verification/"]
123
- UNDR["📂 Under_Verification/"]
124
- TVAL["✅ Temp_Validated/"]
125
- KNOW["📚 Verified/ 可信知识库"]
126
- STATE["🗄️ Progress_Logs/ · VibeMath_State/"]
127
- end
128
-
129
- U -->|"求解 XX / 查进度 / 干预"| M
130
- M -->|"vibe_math_* 工具"| SCHED
131
-
132
- SCHED -->|"① 派发"| BRAIN
133
- BRAIN -->|"多个大相径庭的方向"| SCHED
134
- SCHED -->|"② 每方向一个"| SOLV
135
- SOLV -->|"结构化结果 JSON"| SCHED
136
- SOLV -.->|"迭代至卡死"| DERI
137
- DERI -->|"派生 1~3 个新方向"| SCHED
138
- SCHED -->|"③ 写盘"| PEND
139
- SCHED -->|"④ 拆解为最小验证单元"| UNDR
140
- SCHED -->|"⑤ 派发 ≥3 个"| VERI
141
- VERI -->|"裁决 JSON"| SCHED
142
- SCHED -->|"⑥ 通过"| TVAL
143
- SCHED -->|"⑦ 晋升"| KNOW
144
- SCHED -->|"⑧ 派发"| DECI
145
- DECI -->|"⑨ 已解决 → 回写"| QS
146
- SCHED <-->|"读取问题"| QS
147
- SCHED <-->|"状态落盘 / 断点恢复"| STATE
148
- ```
149
-
150
- **一句话流水线**:`qs.csv` → Brainstorm 拆方向 → 每方向一个 Solver 多轮迭代(卡死则 Derive 派生新方向)→ 输出拆成最小验证单元 → ≥3 个 Verifier 独立审查 → 辩论 → 裁决 → 通过晋升 `Verified/` → Decider 回写 `qs.csv`;全程状态落盘 `VibeMath_State/`,`resume` 断点续跑,`manual` 模式在派发/裁决/晋升处挂起人工决策。
151
-
152
- ---
153
-
154
- ## 🧩 架构图 · v2(新架构 · 概率驱动)
155
-
156
- > 静态 PNG 预览 + 可编辑 Mermaid 图源(GitHub 原生渲染);生成脚本见 [docs/generate_framework_diagram_v2.py](docs/generate_framework_diagram_v2.py)。
157
-
158
- ![Vibe Math V2 架构图](示例图/框架图-v2.png)
159
-
160
- ```mermaid
161
- flowchart TB
162
- subgraph L1["👤 交互层"]
163
- U["😀 用户(自然语言)"]
164
- M["🤖 主代理(助手 + 汇报者)<br/>翻译需求 · 汇报进度 · 问答配置<br/>不求解 · 不调度"]
165
- end
166
-
167
- subgraph L2["⚙️ 调度层(插件代码 · 概率驱动)"]
168
- SCHED["调度器 Scheduler<br/>唯一文件写者 · 按优先级调度<br/>explorer → 逐方向 solver → 验证器 → 收口<br/>断点持久化 · 人工决策门"]
169
- end
170
-
171
- subgraph L3["🧠 子代理层(continuable 持久会话)"]
172
- EXP["🧭 Explorer<br/>拆方向 / 全死路时重派生(去死路 · 并集)"]
173
- SOLV["✍️ Solver × N<br/>agent_self_iteration<br/>逐方向多轮迭代"]
174
- VERI["🔬 Verifier × ≥3<br/>独立审查 → 辩论 → 裁决"]
175
- end
176
-
177
- subgraph L4["💾 数据层 · VibeMath/Projects/&lt;项目&gt;/"]
178
- QS["📋 qs/qs.json<br/>问题 + 解法(正确概率)"]
179
- PRP["📚 Propos/&lt;分类&gt;_Propos.json<br/>命题(布尔估计 · 证明/证伪列表)"]
180
- VERD["✅ Verified/<br/>定论事实(0/1)"]
181
- LOGS["🗄️ Verification_logs/ · Progress_Logs/<br/>· Reliable/ · VibeMath_State/"]
182
- end
183
-
184
- U -->|"求解 / 查进度 / 干预"| M
185
- M -->|"vibe_math_* 工具"| SCHED
186
-
187
- SCHED -->|"① 按优先级取问题"| QS
188
- SCHED -->|"② 派 Explorer"| EXP
189
- EXP -->|"方向集 M_q"| SCHED
190
- SCHED -->|"③ 每方向一个"| SOLV
191
- SOLV -->|"引理 → Propos(概率&lt;1)"| PRP
192
- SOLV -->|"解法 → qs(概率&lt;1)"| QS
193
- SOLV -.->|"卡死 → 重派生"| EXP
194
- SCHED -->|"④ 选 r 派 ≥3 验证器"| VERI
195
- VERI -->|"⑤ 裁决 0/1/中间"| SCHED
196
- SCHED -->|"⑥ 概率=1 → 收口/晋升"| PRP
197
- SCHED -->|"已解决 / 优先级 never"| QS
198
- SCHED -->|"晋升定论"| VERD
199
- SCHED <-->|"辩论记录 / 状态落盘"| LOGS
200
- ```
201
-
202
- **一句话流水线**:`qs.json` 按优先级取问题 → Explorer 拆方向(全死路则重派生)→ 每方向一个 Solver 多轮迭代(引理进 `Propos/`、解法回 `qs.json`,概率均 <1)→ 调度器选 r(命题 / 命题+证明·证伪 / 问题+解法)派 ≥3 验证器独立审查→辩论→裁决 → 概率=1 自动收口(问题 solved、命题 1/0,优先级置 `never`);全程状态落盘,`resume` 断点续跑,`reportMode` 可 file/push/both 汇报。
203
-
204
- ---
205
114
 
206
115
  ## 📁 目录结构
207
116
 
@@ -278,9 +187,9 @@ flowchart TB
278
187
  | `vibe_math_setup` | 返回参数 schema(交互式配置用) |
279
188
  | `vibe_math_save_settings` | 把当前参数存成新默认 |
280
189
  | `vibe_math_template` | 生成默认参数模板文件 |
281
- | `vibe_math_new_project` / `set_project` / `list_projects` | 项目管理 |
190
+ | `vibe_math_new_project` / `vibe_math_set_project` / `vibe_math_list_projects` | 项目管理 |
282
191
  | `vibe_math_list_decisions` / `decide` | 查看 / 裁决人工决策 |
283
- | `vibe_math_list_agents` / `message_agent` / `interrupt_agent` | 查看 / 发消息 / 中断子代理 |
192
+ | `vibe_math_list_agents` / `vibe_math_message_agent` / `vibe_math_interrupt_agent` | 查看 / 发消息 / 中断子代理 |
284
193
 
285
194
  斜杠命令(与工具等价):`/vibe start|resume|pause|abort|status|report|mode <auto|manual>|setup|save|template [global|project]|add <id> <desc>|add-proposition <id> <概述>|list-propositions|project [list|new <name>|<name>]|decisions|agents`
286
195
 
@@ -414,6 +323,7 @@ flowchart TB
414
323
  | `mode` | `auto` | `auto` / `manual` |
415
324
  | `maxParallelThreshold` | 4 | 全局最大并发子代理轮数(新派发前须 active < 阈值) |
416
325
  | `solverMaxRounds` | 3 | 每个求解方向最大迭代轮数(agent_self_iteration 上限) |
326
+ | `directionsPerSolver` | 1 | 每个 solver 提示词附带的方向数量(1 = 只看自己方向、互不干扰;>1 = 附带其他活跃方向摘要用于协调) |
417
327
  | `verifierCount` | 3 | 每个验证对象的独立验证器数量 |
418
328
  | `debateMaxRounds` | 5 | 验证辩论(交流群)最大轮数 |
419
329
  | `verdictMode` | `flat` | `flat` = 均衡机制(不一致判 0.5)/ `forced` = 强制裁决(历史准确率+严谨性加权) |
@@ -456,7 +366,7 @@ flowchart TB
456
366
  - manual 模式在第一个未决关键节点暂停整条主循环。
457
367
 
458
368
  **v2**:
459
- - 安装器只**补装缺失**的 preset 文件,不覆盖你已编辑的预设(删除对应目录即可重新安装)。
369
+ - 安装器带**版本化自动更新**:每次 DSH 启动时对比包版本与 `<presetRoot>/.vibe-math-installed.json` 记录——版本升级会自动替换**未被手动修改**的 preset 文件(哈希一致才覆盖);你改过的文件会被保留并在日志中提示。无记录的老安装首次会一次性刷新到当前版本。想强制全量重装:删除 `~/.dsh/.agent-presets/vibe-math-v1` 与 `vibe-math-v2` 目录后重启 DSH。
460
370
  - `flat` 裁决在辩论不一致时直接判 `0.5`;`forced` 按历史准确率+置信度加权。
461
371
  - `never` 优先级的问题/命题**永不调度**,且不阻塞严格终止(视为主动弃权)。
462
372
  - 两个 preset 文件互相独立、可共存;同一会话同时只能选一个预设。
package/installer.js CHANGED
@@ -1,51 +1,149 @@
1
- // dsh-vibe-math merged bundle installer.
1
+ // dsh-vibe-math merged bundle installer — VERSIONED AUTO-UPDATE.
2
2
  // When this bundle is installed (e.g. `dsh plugin add dsh-vibe-math` or from the
3
3
  // dsh-market), this plugin copies BOTH agent presets out of the package into the
4
4
  // DSH preset root, so the user immediately gets two presets in the picker:
5
5
  // vibe-math-v1/ (classic pipeline architecture)
6
6
  // vibe-math-v2/ (new probability-driven architecture)
7
- // Copy is per-file and only installs MISSING files (idempotent; never clobbers
8
- // a preset the user already edited — delete the dir to force a reinstall).
9
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
7
+ //
8
+ // UPDATE POLICY (state recorded in <presetRoot>/.vibe-math-installed.json):
9
+ // - baseline (no state file e.g. upgrading from an installer that predates
10
+ // this mechanism): every existing owned file is refreshed to the current
11
+ // package version and recorded as package-owned (user policy: auto-update
12
+ // old installs; any manual edits made before this baseline are overwritten
13
+ // once — from then on edits are protected).
14
+ // - upgrade (recorded version != current package.json version): every owned
15
+ // file that is byte-identical to the previously installed copy (i.e. NOT
16
+ // user-edited since) is overwritten with the new version; user-edited files
17
+ // are preserved and reported via the logger.
18
+ // - same version: no-op (idempotent). Missing files are ALWAYS restored.
19
+ // - force a full refresh at any time: delete the preset dirs and restart DSH.
20
+ import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'
21
+ import { createHash } from 'node:crypto'
10
22
  import { homedir } from 'node:os'
11
23
  import { dirname, join } from 'node:path'
12
24
  import { fileURLToPath } from 'node:url'
13
25
 
14
26
  export const name = 'vibe-math-preset-installer'
15
27
 
28
+ const PRESETS = [
29
+ {
30
+ src: 'vibe-math-v1',
31
+ dst: 'vibe-math-v1',
32
+ files: ['agent.cordis.yml', 'preset.yml', 'vibe-math.js', '实现方案-多代理数学问题求解与验证框架.md'],
33
+ },
34
+ {
35
+ src: 'vibe-math-v2',
36
+ dst: 'vibe-math-v2',
37
+ files: ['agent.cordis.yml', 'preset.yml', 'vibe-math-v2.js', '实现方案.md'],
38
+ },
39
+ ]
40
+
41
+ const STATE_FILE = '.vibe-math-installed.json'
42
+
43
+ function sha256(buf) { return createHash('sha256').update(buf).digest('hex') }
44
+
45
+ function readState(path) {
46
+ try {
47
+ const raw = readFileSync(path, 'utf8')
48
+ const obj = JSON.parse(raw)
49
+ if (obj && typeof obj === 'object' && obj.files && typeof obj.files === 'object') return obj
50
+ } catch (e) { /* missing or corrupt — treat as no state (baseline) */ }
51
+ return null
52
+ }
53
+
54
+ function writeState(path, state) {
55
+ try {
56
+ const tmp = path + '.tmp'
57
+ writeFileSync(tmp, JSON.stringify(state, null, 2) + '\n', 'utf8')
58
+ renameSync(tmp, path)
59
+ } catch (e) {
60
+ // best-effort: state persistence failure must not break the copy step
61
+ }
62
+ }
63
+
16
64
  export function apply(ctx) {
17
65
  const logger = ctx && ctx.logger
18
66
  try {
19
67
  const dshHome = process.env.DSH_HOME || join(homedir(), '.dsh')
20
68
  const here = dirname(fileURLToPath(import.meta.url))
21
- const targets = [
22
- {
23
- src: join(here, 'vibe-math-v1'),
24
- dst: join(dshHome, '.agent-presets', 'vibe-math-v1'),
25
- files: ['agent.cordis.yml', 'preset.yml', 'vibe-math.js', '实现方案-多代理数学问题求解与验证框架.md'],
26
- },
27
- {
28
- src: join(here, 'vibe-math-v2'),
29
- dst: join(dshHome, '.agent-presets', 'vibe-math-v2'),
30
- files: ['agent.cordis.yml', 'preset.yml', 'vibe-math-v2.js', '实现方案.md'],
31
- },
32
- ]
33
- let installed = 0
34
- for (const t of targets) {
35
- if (!existsSync(t.src)) continue
36
- mkdirSync(t.dst, { recursive: true })
37
- for (const f of t.files) {
38
- const s = join(t.src, f)
39
- const d = join(t.dst, f)
40
- if (!existsSync(s) || existsSync(d)) continue
41
- writeFileSync(d, readFileSync(s))
42
- installed += 1
69
+ const presetRoot = join(dshHome, '.agent-presets')
70
+ const stateFile = join(presetRoot, STATE_FILE)
71
+
72
+ // current package version (the source of truth for "is this an upgrade?")
73
+ let pkgVersion = ''
74
+ try { pkgVersion = String((JSON.parse(readFileSync(join(here, 'package.json'), 'utf8')).version) || '') } catch (e) { pkgVersion = '' }
75
+
76
+ const state = readState(stateFile)
77
+ const prevFiles = (state && state.files) || {}
78
+ const isUpgrade = state !== null && pkgVersion !== '' && state.version !== pkgVersion
79
+ const isBaseline = state === null // no recorded history → refresh everything (user policy: auto-update old installs)
80
+
81
+ const nextFiles = {}
82
+ let installed = 0, updated = 0, kept = 0
83
+ const keptList = []
84
+
85
+ for (const p of PRESETS) {
86
+ const srcDir = join(here, p.src)
87
+ const dstDir = join(presetRoot, p.dst)
88
+ if (!existsSync(srcDir)) continue
89
+ mkdirSync(dstDir, { recursive: true })
90
+ for (const f of p.files) {
91
+ const s = join(srcDir, f)
92
+ const d = join(dstDir, f)
93
+ if (!existsSync(s)) continue
94
+ const key = p.src + '/' + f
95
+ const cur = readFileSync(s)
96
+ const curHash = sha256(cur)
97
+ if (!existsSync(d)) {
98
+ // missing file: always restore, whatever the version
99
+ writeFileSync(d, cur)
100
+ installed += 1
101
+ nextFiles[key] = { hash: curHash, provenance: 'package' }
102
+ continue
103
+ }
104
+ const destHash = sha256(readFileSync(d))
105
+ if (isBaseline) {
106
+ // no recorded history: refresh to the current package (one-time; edits
107
+ // made before this mechanism are overwritten, later edits are protected)
108
+ if (destHash === curHash) { nextFiles[key] = { hash: curHash, provenance: 'package' } }
109
+ else { writeFileSync(d, cur); updated += 1; nextFiles[key] = { hash: curHash, provenance: 'package' } }
110
+ continue
111
+ }
112
+ const prev = prevFiles[key]
113
+ const prevRec = (prev && typeof prev === 'object') ? prev : { hash: prev, provenance: 'package' }
114
+ const prevProv = (prevRec.provenance === 'user') ? 'user' : 'package' // 未知来源按包文件处理
115
+ if (prevProv === 'package' && destHash === prevRec.hash) {
116
+ // 包文件且未被改动 → 可安全升级(内容相同则跳过写入)
117
+ if (destHash !== curHash) { writeFileSync(d, cur); updated += 1 }
118
+ nextFiles[key] = { hash: curHash, provenance: 'package' }
119
+ } else if (prevProv === 'user') {
120
+ // 用户持有 → 永不覆盖
121
+ kept += 1
122
+ if (isUpgrade) keptList.push(key + ' (用户持有)')
123
+ nextFiles[key] = { hash: destHash, provenance: 'user' }
124
+ } else {
125
+ // 包文件但自上次安装后已被用户改动
126
+ kept += 1
127
+ if (isUpgrade) keptList.push(key + ' (已修改)')
128
+ nextFiles[key] = { hash: destHash, provenance: 'user' }
129
+ }
43
130
  }
44
131
  }
45
- if (installed > 0) {
46
- logger?.info?.('[dsh-vibe-math] installed ' + installed + ' preset file(s) — presets vibe-math-v1 & vibe-math-v2 are now available in the preset picker (new session)')
132
+
133
+ writeState(stateFile, { version: pkgVersion, files: nextFiles, updatedAt: Date.now() })
134
+
135
+ if (isUpgrade) {
136
+ logger?.info?.('[dsh-vibe-math] preset auto-update: version ' + (state.version || '(none)') + ' → ' + pkgVersion +
137
+ ' — 新增 ' + installed + ' 个文件,更新 ' + updated + ' 个文件' +
138
+ (kept > 0 ? ',保留 ' + kept + ' 个未覆盖文件(' + keptList.join('; ') + ')' : '') +
139
+ '。新版本 preset 将在新会话生效。')
140
+ } else if (isBaseline) {
141
+ logger?.info?.('[dsh-vibe-math] preset baseline: refreshed ' + (installed + updated) + ' file(s) to v' + pkgVersion +
142
+ ' — 已启用自动更新(后续版本升级将自动替换未被手动修改的 preset 文件)。')
143
+ } else if (installed > 0) {
144
+ logger?.info?.('[dsh-vibe-math] restored ' + installed + ' missing preset file(s)')
47
145
  }
48
146
  } catch (err) {
49
- logger?.warn?.('[dsh-vibe-math] preset install failed: %s', String((err && err.message) || err))
147
+ logger?.warn?.('[dsh-vibe-math] preset install/update failed: %s', String((err && err.message) || err))
50
148
  }
51
149
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "dsh-vibe-math",
3
3
  "description": "Multi-agent mathematical problem-solving & verification frameworks for DeepSeek Harness — TWO agent presets in one install: vibe-math-v1 (classic pipeline: brainstorm → solver iteration → multi-verifier debate → Verified) and vibe-math-v2 (new probability-driven architecture: qs.json + Propos knowledge base + explorer→solver→review/debate verdict). Installing this bundle auto-installs both presets into the DSH preset root.",
4
- "version": "0.3.4",
4
+ "version": "0.3.6",
5
5
  "type": "module",
6
6
  "main": "installer.js",
7
7
  "exports": {
@@ -34,6 +34,7 @@ export function apply(ctx) {
34
34
  mode: 'auto', // auto | manual
35
35
  maxParallelThreshold: 4, // concurrency gate: active turns < this
36
36
  solverMaxRounds: 3, // per-direction iteration cap (spec example)
37
+ directionsPerSolver: 1, // 每个 solver 提示词附带的方向数量(1 = 只看自己方向)
37
38
  verifierCount: 3, // independent reviewers per verification
38
39
  debateMaxRounds: 5, // debate round cap (spec example)
39
40
  verdictMode: 'flat', // flat = 均衡机制(0.5) | forced = 强制裁决(weighted)
@@ -119,6 +120,7 @@ export function apply(ctx) {
119
120
  { name: 'mode', type: 'enum', options: ['auto', 'manual'], description: 'auto = 无人值守自动通过关键节点;manual = 关键节点挂起人工决策', suggestion: 'auto' },
120
121
  { name: 'maxParallelThreshold', type: 'integer', description: '全局最大并发子代理轮数(新派发前须满足 active < 阈值)', suggestion: 4 },
121
122
  { name: 'solverMaxRounds', type: 'integer', description: '每个求解方向的最大迭代轮数(agent_self_iteration 上限)', suggestion: 3 },
123
+ { name: 'directionsPerSolver', type: 'integer', description: '每个 solver 提示词附带的方向数量:1 = 只看自己方向(互不干扰);>1 = 额外附带其他活跃方向摘要用于协调', suggestion: 1 },
122
124
  { name: 'verifierCount', type: 'integer', description: '每个验证对象的独立验证器数量', suggestion: 3 },
123
125
  { name: 'debateMaxRounds', type: 'integer', description: '验证辩论(交流群)最大轮数', suggestion: 5 },
124
126
  { name: 'verdictMode', type: 'enum', options: ['flat', 'forced'], description: 'flat = 均衡机制(不一致直接判 0.5);forced = 强制裁决(按历史准确率+严谨性加权)', suggestion: 'flat' },
@@ -164,7 +166,7 @@ export function apply(ctx) {
164
166
  // ================= settings =================
165
167
  function sanitizeParams(obj) {
166
168
  const out = {}
167
- const intFields = ['maxParallelThreshold', 'solverMaxRounds', 'verifierCount', 'debateMaxRounds', 'solverMaxToolCalls', 'verifierMaxToolCalls', 'reportIntervalMs', 'tickIntervalMs', 'activityLogCap', 'maxExplorerRetries']
169
+ const intFields = ['maxParallelThreshold', 'solverMaxRounds', 'directionsPerSolver', 'verifierCount', 'debateMaxRounds', 'solverMaxToolCalls', 'verifierMaxToolCalls', 'reportIntervalMs', 'tickIntervalMs', 'activityLogCap', 'maxExplorerRetries']
168
170
  const numFields = ['promoteValueThreshold']
169
171
  const arrayFields = ['solverToolAllow', 'solverToolDeny', 'verifierToolAllow', 'verifierToolDeny']
170
172
  for (const k of Object.keys(DEFAULT_PARAMS)) {
@@ -397,6 +399,16 @@ export function apply(ctx) {
397
399
  (d.lessons && d.lessons.length ? ' | lessons: ' + d.lessons.join('; ') : '') +
398
400
  (d.blockers && d.blockers.length ? ' | blockers: ' + d.blockers.join('; ') : '')
399
401
  }
402
+ // 每个 solver 默认只看自己方向(互不干扰):round>1 时带上自己的历史进度,
403
+ // directionsPerSolver>1 时再附带其他活跃方向摘要用于协调(总数不超过该参数)。
404
+ function buildSolverContext(all, own, round, perSolver) {
405
+ const out = []
406
+ const n = Math.max(1, Number(perSolver) || 1)
407
+ if (round > 1) out.push(own)
408
+ const others = all.filter(function (d) { return d.id !== own.id && d.status === 'active' })
409
+ for (let i = 0; i < others.length && out.length < n; i++) out.push(others[i])
410
+ return out.map(directionSummary).join('\n')
411
+ }
400
412
  function solverPrompt(q, dir, round, progressText) {
401
413
  let head = solverPersonaText() + 'You are a dedicated solver agent working ONE solution direction of a math problem (agent_self_iteration).\n\n'
402
414
  head += 'PROBLEM (id: ' + q.id + '): ' + q.概述 + '\nDIRECTION: ' + dir.title + ' (method: ' + dir.method + '; core assumption: ' + dir.core_assumption + ')\nROUND: ' + round + ' of ' + params.solverMaxRounds + '\n'
@@ -688,7 +700,7 @@ export function apply(ctx) {
688
700
  if (dir.status === 'success' || dir.status === 'dead-end') continue
689
701
  const running = Object.keys(agentRegistry).some(function (cid) { const m = agentRegistry[cid]; return m && m.qid === q.id && m.direction === dir.id && m.role === 'solver' })
690
702
  if (running) continue
691
- const progressText = prog.directions.map(directionSummary).join('\n')
703
+ const progressText = buildSolverContext(prog.directions, dir, 1, params.directionsPerSolver)
692
704
  const promptText = solverPrompt(q, dir, 1, progressText)
693
705
  const r = await maybeGate('spawn', 'solver for problem ' + q.id + ' direction ' + dir.id, { label: 'solver:' + q.id + ':' + dir.id, promptText: promptText, meta: { role: 'solver', qid: q.id, direction: dir.id, round: 1, description: q.概述 } }, async function (d) { await spawnChild(d.label, d.promptText, d.meta); return { spawned: true } })
694
706
  if (r && r.gated) return
@@ -743,7 +755,7 @@ export function apply(ctx) {
743
755
  delete agentRegistry[childId]
744
756
  logActivity('solver', qid + '/' + dirId + ' dead-end (success without solution)')
745
757
  } else {
746
- const progressText = prog.directions.map(directionSummary).join('\n')
758
+ const progressText = buildSolverContext(prog.directions, dir, meta.round + 1, params.directionsPerSolver)
747
759
  await followupChild(childId, solverPrompt(q, dir, meta.round + 1, progressText))
748
760
  agentRegistry[childId].round = meta.round + 1
749
761
  dir.round = meta.round + 1
@@ -755,7 +767,7 @@ export function apply(ctx) {
755
767
  delete agentRegistry[childId]
756
768
  logActivity('solver', qid + '/' + dirId + ' dead-end: ' + dir.dead_end_reason)
757
769
  } else {
758
- const progressText = prog.directions.map(directionSummary).join('\n')
770
+ const progressText = buildSolverContext(prog.directions, dir, meta.round + 1, params.directionsPerSolver)
759
771
  if (!scheduler.running) {
760
772
  // paused/aborted: stop the follow-up chain; keep the direction active for resume
761
773
  delete agentRegistry[childId]
@@ -1095,7 +1107,7 @@ export function apply(ctx) {
1095
1107
  registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
1096
1108
  registerTool('vibe_math_report', 'Return the full progress report and write it to Progress_Logs/report.json.', objParams({}), async function () { await maybeWriteReport(true); return await buildReport() })
1097
1109
  registerTool('vibe_math_set_mode', 'Switch between manual and auto (preset) mode. Switching to auto auto-resolves any pending manual decisions.', objParams({ mode: { type: 'string', enum: ['manual', 'auto'] } }, ['mode']), async function (args) { params.mode = args.mode; await saveAll(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } })
1098
- registerTool('vibe_math_set_params', 'Update scheduler parameters (partial).', objParams({ maxParallelThreshold: { type: 'integer' }, solverMaxRounds: { type: 'integer' }, verifierCount: { type: 'integer' }, debateMaxRounds: { type: 'integer' }, verdictMode: { type: 'string', enum: ['flat', 'forced'] }, reportMode: { type: 'string', enum: ['file', 'push', 'both'] }, promoteValueThreshold: { type: 'number' }, priorityAdjust: { type: 'string', enum: ['none', 'deadend-deprioritize', 'survival-map'] }, proposPriorityAdjust: { type: 'string', enum: ['none', 'progress-graded'] }, provider: { type: 'string' }, model: { type: 'string' }, solverPersona: { type: 'string' }, verifierPersona: { type: 'string' }, solverToolAllow: { type: 'array', items: { type: 'string' } }, solverToolDeny: { type: 'array', items: { type: 'string' } }, verifierToolAllow: { type: 'array', items: { type: 'string' } }, verifierToolDeny: { type: 'array', items: { type: 'string' } }, solverMaxToolCalls: { type: 'integer' }, verifierMaxToolCalls: { type: 'integer' }, reportIntervalMs: { type: 'integer' }, tickIntervalMs: { type: 'integer' }, activityLogCap: { type: 'integer' }, maxExplorerRetries: { type: 'integer' } }), async function (args) { params = Object.assign({}, params, sanitizeParams(args)); await saveAll(); return { ok: true, params: params } })
1110
+ registerTool('vibe_math_set_params', 'Update scheduler parameters (partial).', objParams({ maxParallelThreshold: { type: 'integer' }, solverMaxRounds: { type: 'integer' }, verifierCount: { type: 'integer' }, debateMaxRounds: { type: 'integer' }, verdictMode: { type: 'string', enum: ['flat', 'forced'] }, reportMode: { type: 'string', enum: ['file', 'push', 'both'] }, promoteValueThreshold: { type: 'number' }, priorityAdjust: { type: 'string', enum: ['none', 'deadend-deprioritize', 'survival-map'] }, proposPriorityAdjust: { type: 'string', enum: ['none', 'progress-graded'] }, provider: { type: 'string' }, model: { type: 'string' }, solverPersona: { type: 'string' }, verifierPersona: { type: 'string' }, solverToolAllow: { type: 'array', items: { type: 'string' } }, solverToolDeny: { type: 'array', items: { type: 'string' } }, verifierToolAllow: { type: 'array', items: { type: 'string' } }, verifierToolDeny: { type: 'array', items: { type: 'string' } }, solverMaxToolCalls: { type: 'integer' }, verifierMaxToolCalls: { type: 'integer' }, reportIntervalMs: { type: 'integer' }, tickIntervalMs: { type: 'integer' }, activityLogCap: { type: 'integer' }, maxExplorerRetries: { type: 'integer' }, directionsPerSolver: { type: 'integer' } }), async function (args) { params = Object.assign({}, params, sanitizeParams(args)); await saveAll(); return { ok: true, params: params } })
1099
1111
  registerTool('vibe_math_setup', 'Return the interactive parameter schema for guided configuration.', objParams({}), async function () { const list = PARAM_SCHEMA.map(function (p) { const out = Object.assign({}, p); out.current = params[p.name]; out.default = DEFAULT_PARAMS[p.name]; return out }); return { ok: true, parameters: list, saveTo: frameworkRoot() + '/vibe_math_setting.json' } })
1100
1112
  registerTool('vibe_math_save_settings', 'Write the current params to vibe_math_setting.json (JSON with comments) as new defaults.', objParams({}), async function () { return await saveSettings() })
1101
1113
  registerTool('vibe_math_template', 'Create a fresh vibe_math_setting.json template (with defaults + comments) in the workspace (global) or current project folder.', objParams({ where: { type: 'string', enum: ['global', 'project'] } }), async function (args) { return await createTemplate((args && args.where) || 'global') })