dsh-vibe-math 0.3.8 → 0.3.9

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
@@ -340,9 +340,12 @@ dsh plugin --profile <你的 profile> add github:ChongCyrus/Vibe-Mathematics
340
340
  | `priorityAdjust` | `none` | `none` / `deadend-deprioritize`(全死路降优先级)/ `survival-map`(按存活率重算) |
341
341
  | `proposPriorityAdjust` | `none` | 命题优先级动态调整:`none` / `progress-graded`(按定论接近度+证明/证伪材料量重算,越接近定论越优先验证) |
342
342
  | `provider` / `model` | 空 | 子代理模型(空 = 继承根代理) |
343
- | `solverPersona` / `verifierPersona` | 空 | 注入求解器/验证器的额外要求 |
343
+ | `solverPersona` / `verifierPersona` / `explorerPersona` | 空 | 注入求解器/验证器/explorer 提示词开头的人格/要求 |
344
+ | `knowledgeContext` | 空 | 共享知识/数据模型说明(空 = 内置完整版:对象/属性定义、概率语义、文件夹用途、输出完整性要求;非空 = 覆盖并注入所有子代理提示词) |
344
345
  | `solverToolAllow` / `solverToolDeny` | `[]` | 求解器允许/禁止的工具 |
345
346
  | `verifierToolAllow` / `verifierToolDeny` | `[]` | 验证器允许/禁止的工具 |
347
+ | `solverAllowNetwork` / `verifierAllowNetwork` | 空 | 网络工具开关(web_search/web/fetch):空=继承全部;`true`=在已有 allow 列表时补入;`false`=禁止 |
348
+ | `solverAllowScripts` / `verifierAllowScripts` | 空 | 脚本工具开关(bash/pwsh):同上 |
346
349
  | `solverMaxToolCalls` / `verifierMaxToolCalls` | 0 | 每轮外部工具调用上限(0=不限) |
347
350
  | `reportIntervalMs` | 0 | 0 = 仅事件驱动(有状态更新才写/推);>0 = 定时自动汇报(毫秒) |
348
351
  | `tickIntervalMs` | 2000 | 调度器心跳间隔(毫秒) |
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.8",
4
+ "version": "0.3.9",
5
5
  "type": "module",
6
6
  "main": "installer.js",
7
7
  "exports": {
@@ -42,10 +42,16 @@ export function apply(ctx) {
42
42
  model: '',
43
43
  solverPersona: '',
44
44
  verifierPersona: '',
45
+ explorerPersona: '', // 注入每个 explorer/rederive 提示词开头的人格/要求
46
+ knowledgeContext: '', // 共享知识/数据模型说明(空 = 使用内置完整版;非空 = 覆盖)
45
47
  solverToolAllow: [],
46
48
  solverToolDeny: [],
47
49
  verifierToolAllow: [],
48
50
  verifierToolDeny: [],
51
+ solverAllowNetwork: '', // '' = 继承全部;true = 允许网络工具;false = 禁止
52
+ verifierAllowNetwork: '',
53
+ solverAllowScripts: '', // '' = 继承全部;true = 允许脚本工具;false = 禁止
54
+ verifierAllowScripts: '',
49
55
  solverMaxToolCalls: 0,
50
56
  verifierMaxToolCalls: 0,
51
57
  reportIntervalMs: 0, // 0 = 仅事件驱动(有代理状态更新等事件才写/推报告);>0 = 定时自动汇报(毫秒)
@@ -128,10 +134,16 @@ export function apply(ctx) {
128
134
  { name: 'model', type: 'string', description: '子代理模型 id(空 = 继承根代理)', suggestion: '' },
129
135
  { name: 'solverPersona', type: 'string', description: '注入每个求解器提示词开头的人格/要求', suggestion: '' },
130
136
  { name: 'verifierPersona', type: 'string', description: '注入每个验证器提示词开头的人格/要求', suggestion: '' },
137
+ { name: 'explorerPersona', type: 'string', description: '注入每个 explorer/重派生提示词开头的人格/要求', suggestion: '' },
138
+ { name: 'knowledgeContext', type: 'string', description: '共享知识/数据模型说明(空 = 内置完整版;非空 = 覆盖,注入 explorer/solver/verifier 提示词)', suggestion: '' },
131
139
  { name: 'solverToolAllow', type: 'string[]', description: '求解器允许的工具名列表(空 = 继承全部工具)', suggestion: [] },
132
140
  { name: 'solverToolDeny', type: 'string[]', description: '求解器禁止的工具名列表', suggestion: [] },
133
141
  { name: 'verifierToolAllow', type: 'string[]', description: '验证器允许的工具名列表', suggestion: [] },
134
142
  { name: 'verifierToolDeny', type: 'string[]', description: '验证器禁止的工具名列表', suggestion: [] },
143
+ { name: 'solverAllowNetwork', type: 'boolean', description: '求解器网络工具开关:空=继承全部;true=允许(在已有 allow 列表时补入网络工具);false=禁止 web_search/web/fetch', suggestion: '' },
144
+ { name: 'verifierAllowNetwork', type: 'boolean', description: '验证器网络工具开关(同 solverAllowNetwork)', suggestion: '' },
145
+ { name: 'solverAllowScripts', type: 'boolean', description: '求解器脚本工具开关:空=继承全部;true=允许(在已有 allow 列表时补入);false=禁止 bash/pwsh', suggestion: '' },
146
+ { name: 'verifierAllowScripts', type: 'boolean', description: '验证器脚本工具开关(同 solverAllowScripts)', suggestion: '' },
135
147
  { name: 'solverMaxToolCalls', type: 'integer', description: '求解器每轮外部工具调用上限(0 = 不限)', suggestion: 0 },
136
148
  { name: 'verifierMaxToolCalls', type: 'integer', description: '验证器每轮外部工具调用上限(0 = 不限)', suggestion: 0 },
137
149
  { name: 'reportIntervalMs', type: 'integer', description: '进度汇报间隔(毫秒):0 = 仅事件驱动(有代理状态更新等事件才写/推报告);>0 = 同时按该间隔定时自动汇报', suggestion: 0 },
@@ -180,6 +192,7 @@ export function apply(ctx) {
180
192
  else if (k === 'reportMode') { out[k] = (v === 'file' || v === 'push' || v === 'both') ? v : DEFAULT_PARAMS[k] }
181
193
  else if (k === 'priorityAdjust') { out[k] = (v === 'none' || v === 'deadend-deprioritize' || v === 'survival-map') ? v : DEFAULT_PARAMS[k] }
182
194
  else if (k === 'proposPriorityAdjust') { out[k] = (v === 'none' || v === 'progress-graded') ? v : DEFAULT_PARAMS[k] }
195
+ else if (k === 'solverAllowNetwork' || k === 'verifierAllowNetwork' || k === 'solverAllowScripts' || k === 'verifierAllowScripts') { out[k] = (v === true || v === false || v === '') ? v : DEFAULT_PARAMS[k] }
183
196
  else { out[k] = v }
184
197
  }
185
198
  return out
@@ -337,7 +350,9 @@ export function apply(ctx) {
337
350
  // ================= child spawn / followup =================
338
351
  function pickProvider() { try { const names = subagents.list ? subagents.list() : []; if (names.indexOf('spawn') !== -1) return 'spawn'; if (names.indexOf('fork') !== -1) return 'fork' } catch (e) {} return 'spawn' }
339
352
  function childAgentOptions() { const o = {}; try { if (rootAgent && rootAgent.options) { if (rootAgent.options.provider) o.provider = rootAgent.options.provider; if (rootAgent.options.model) o.model = rootAgent.options.model } } catch (e) {} if (params.provider) o.provider = params.provider; if (params.model) o.model = params.model; return o }
340
- function buildToolFilter(role) { const allow = role === 'solver' ? params.solverToolAllow : role === 'verifier' ? params.verifierToolAllow : undefined; const deny = role === 'solver' ? params.solverToolDeny : role === 'verifier' ? params.verifierToolDeny : undefined; const f = {}; if (Array.isArray(allow) && allow.length > 0) f.allow = allow.slice(); if (Array.isArray(deny) && deny.length > 0) f.deny = deny.slice(); return (f.allow || f.deny) ? f : undefined }
353
+ const NETWORK_TOOLS = ['web_search', 'web', 'fetch']
354
+ const SCRIPT_TOOLS = ['bash', 'pwsh']
355
+ function buildToolFilter(role) { const allow = role === 'solver' ? params.solverToolAllow : role === 'verifier' ? params.verifierToolAllow : undefined; const deny = role === 'solver' ? params.solverToolDeny : role === 'verifier' ? params.verifierToolDeny : undefined; const net = role === 'solver' ? params.solverAllowNetwork : role === 'verifier' ? params.verifierAllowNetwork : undefined; const scr = role === 'solver' ? params.solverAllowScripts : role === 'verifier' ? params.verifierAllowScripts : undefined; let a = Array.isArray(allow) ? allow.slice() : []; let d = Array.isArray(deny) ? deny.slice() : []; if (net === false) d = d.concat(NETWORK_TOOLS); else if (net === true && a.length > 0) a = a.concat(NETWORK_TOOLS); if (scr === false) d = d.concat(SCRIPT_TOOLS); else if (scr === true && a.length > 0) a = a.concat(SCRIPT_TOOLS); const f = {}; if (a.length > 0) f.allow = a; if (d.length > 0) f.deny = d; return (f.allow || f.deny) ? f : undefined }
341
356
  async function spawnChild(label, promptText, meta) {
342
357
  const request = { prompt: [textBlock(promptText)], parent: rootAgent, agentOptions: childAgentOptions() }
343
358
  const tf = buildToolFilter(meta && meta.role); if (tf) request.toolFilter = tf
@@ -356,9 +371,39 @@ export function apply(ctx) {
356
371
  // ================= prompts =================
357
372
  function solverPersonaText() { return params.solverPersona ? (String(params.solverPersona) + '\n\n') : '' }
358
373
  function verifierPersonaText() { return params.verifierPersona ? (String(params.verifierPersona) + '\n\n') : '' }
374
+ function explorerPersonaText() { return params.explorerPersona ? (String(params.explorerPersona) + '\n\n') : '' }
375
+ // 共享知识/数据模型说明(点6):完整解释各对象/属性含义、概率语义、文件夹用途、输出要求。
376
+ // 空参数 = 使用内置完整版;非空 = 由用户覆盖(点8)。
377
+ function defaultKnowledgeContext() {
378
+ return 'KNOWLEDGE BASE & DATA MODEL (definition contract you MUST follow):\n' +
379
+ '\n1) PROBABILITY SEMANTICS — the single most important rule:\n' +
380
+ '- 正确概率 / 布尔估计 ∈ [0,1]。\n' +
381
+ '- 1 = 绝对正确(已被证明且验证通过):你可以把它当作已知事实/可信结论直接用于推理。\n' +
382
+ '- 0 = 绝对错误(已被证伪且验证通过)。\n' +
383
+ '- 0 与 1 之间的任何值 = 未定论/待验证:只能作为参考证据,绝不能当作已成立的事实引用。\n' +
384
+ '- Verified/ 中的卡片概率恒为 1 或 0,内容可信、可直接引用。\n' +
385
+ '\n2) OBJECT MODELS (按实现方案):\n' +
386
+ '- 问题 PROBLEM(qs/qs.json):{ id, 概述(完整问题陈述,所提到的每个对象/记号都要给出完整定义), 已解决(bool), 解法列表:[{ 完整解法(详细步骤), 正确概率, 已验 }], 优先级(整数,越小越优先调度;"never"=永不调度), progress(历史:已试方向、各方向路线、阻碍及原因、教训、可行性评估)}。\n' +
387
+ '- 命题 PROPOSITION(Propos/<分类>_Propos.json):{ id, 概述(完整陈述), 布尔估计(该命题为真的概率), 细类型(分类 JSON), 证明列表:[{ 完整过程(完整证明), 正确概率, 支持信息/依据 }], 证伪列表:[{ 完整过程(完整证伪), 正确概率, 支持信息/依据 }], 优先级, 价值/关键性(0-1,重要性), progress(过往尝试与教训)}。\n' +
388
+ '- 收口规则:问题的某个解法 正确概率=1 → 问题已解决;命题的证明/证伪条目 正确概率=1 → 命题布尔估计=1/0(已定论)。\n' +
389
+ '\n3) FOLDERS (per project, VibeMath/Projects/<project>/):\n' +
390
+ '- qs/qs.json:问题清单——求解与验证的唯一问题来源。\n' +
391
+ '- Propos/<分类>_Propos.json:命题知识库(已有认知)。\n' +
392
+ '- Reliable/:可信参考文献(只读)。\n' +
393
+ '- Verified/<分类>_Verified.json:定论事实索引——布尔估计=0/1 的命题卡片与已解决问题卡片;内容可信、可直接使用。\n' +
394
+ '- Verification_logs/:辩论记录。Progress_Logs/:进度与报告。VibeMath_State/:调度器私有状态——不要读也不要改。\n' +
395
+ '\n4) OUTPUT REQUIREMENTS (你输出的每个对象必须满足):\n' +
396
+ '- 完整性、不断章取义:任何你写出的问题/命题/结论都要给出完整陈述,并把它所依赖的对象、环境、背景、定义全部补全(例如提到某个序列/函数/定理时给出其完整定义与假设)。\n' +
397
+ '- 若结论依赖某个临时假设 p,必须显式写成「若 <p 的完整陈述> 成立,则:...」(同样要定义完整)。\n' +
398
+ '- 只输出规定的 JSON(放在 ```json 代码围栏内),JSON 之外不写任何内容。\n'
399
+ }
400
+ function knowledgeContextText() { const k = params.knowledgeContext ? String(params.knowledgeContext) : defaultKnowledgeContext(); return k ? ('\n' + k + '\n') : '' }
359
401
  function capabilitiesText(role) {
360
402
  const maxCalls = role === 'solver' ? params.solverMaxToolCalls : params.verifierMaxToolCalls
403
+ const netOn = role === 'solver' ? params.solverAllowNetwork : params.verifierAllowNetwork
404
+ const scrOn = role === 'solver' ? params.solverAllowScripts : params.verifierAllowScripts
361
405
  let t = '\nYOUR PERMISSIONS / CAPABILITIES:\n'
406
+ t += '- Network tools (web search / fetch): ' + (netOn === false ? 'DISABLED for you' : 'available') + '; Script/shell tools (bash/pwsh): ' + (scrOn === false ? 'DISABLED for you' : 'available') + ' (your actual tool list is enforced by the framework).\n'
362
407
  t += '- You may READ any file under Verified/ as a known, trusted dependency (resolved facts).\n'
363
408
  t += '- You should BASE your reasoning on the existing knowledge under Propos/ (propositions with proofs/refutations and probabilities) and Reliable/ (trusted references).\n'
364
409
  t += '- You may use external tools (web search, symbolic/numeric computation, literature lookup) to assist; '
@@ -371,7 +416,8 @@ export function apply(ctx) {
371
416
  return t
372
417
  }
373
418
  function explorerPrompt(q) {
374
- return 'You are a research mathematician orchestrating strategy for one problem.\n\nPROBLEM (id: ' + q.id + '): ' + q.概述 + '\n\n' +
419
+ return explorerPersonaText() + 'You are a research mathematician orchestrating strategy for one problem.\n\nPROBLEM (id: ' + q.id + '): ' + q.概述 + '\n\n' +
420
+ knowledgeContextText() +
375
421
  capabilitiesText('solver') +
376
422
  '\nDo a first-stage METACOGNITIVE BRAINSTORM: decompose constraints, test boundary/extreme cases, map to similar known problems. ' +
377
423
  'Then propose 3-6 DIVERSE, mutually distinct solution directions (e.g. analytic method, constructive proof, contradiction, numeric approximation + limit passage, categorical abstraction, ...). ' +
@@ -384,7 +430,8 @@ export function apply(ctx) {
384
430
  return '- ' + d.id + '「' + d.title + '」status=' + d.status + ' round=' + d.round + ' survival=' + d.survival + (d.dead_end_reason ? ' [blocker: ' + d.dead_end_reason + ']' : '') +
385
431
  (d.routes && d.routes.length ? ' | routes: ' + d.routes.map(function (r) { return r.title + '[' + (r.feasibility_signal || '') + ']' }).join('; ') : '')
386
432
  }).join('\n')
387
- return 'You are a research mathematician re-deriving strategy for a problem whose prior directions stalled or failed.\n\nPROBLEM (id: ' + q.id + '): ' + q.概述 + '\n\nPRIOR DIRECTIONS (with blockers):\n' + prior + '\n' +
433
+ return explorerPersonaText() + 'You are a research mathematician re-deriving strategy for a problem whose prior directions stalled or failed.\n\nPROBLEM (id: ' + q.id + '): ' + q.概述 + '\n\nPRIOR DIRECTIONS (with blockers):\n' + prior + '\n' +
434
+ knowledgeContextText() +
388
435
  capabilitiesText('solver') +
389
436
  '\nQuantitatively analyze the historical progress, blocker causes, and feasibility decay of each prior direction. Discard directions already proven to be dead ends (unless a new tool/idea changes that). ' +
390
437
  'Then deeply DERIVE 1-3 BRAND-NEW directions never tried before, each with a one-line motivation. ' +
@@ -413,16 +460,17 @@ export function apply(ctx) {
413
460
  let head = solverPersonaText() + 'You are a dedicated solver agent working ONE solution direction of a math problem (agent_self_iteration).\n\n'
414
461
  head += 'PROBLEM (id: ' + q.id + '): ' + q.概述 + '\nDIRECTION: ' + dir.title + ' (method: ' + dir.method + '; core assumption: ' + dir.core_assumption + ')\nROUND: ' + round + ' of ' + params.solverMaxRounds + '\n'
415
462
  if (round > 1 || (progressText && progressText.length)) head += '\nYOUR PRIOR PROGRESS / OTHER DIRECTIONS:\n' + progressText + '\n'
463
+ head += knowledgeContextText()
416
464
  head += capabilitiesText('solver')
417
465
  head += '\nStart from the last recorded node of direction ' + dir.id + ' (inherit progress, or branch a sub-route under it). Each round you MUST produce, even if incomplete:\n' +
418
466
  '- new lemmas / intermediate conclusions WITH full proofs (these go to the Propos/ knowledge base);\n' +
419
467
  '- each concrete sub-route tried, its progress overview, an EXPLICIT feasibility signal (e.g. "unremovable singularity", "conflicts with known theorem X"), and any blocker;\n' +
420
468
  '- lessons learned from failed attempts (what to avoid, what did not work and why);\n' +
421
469
  '- an updated survival probability for this direction.\n'
422
- head += '\nIf you encounter an EXTREMELY complex auxiliary conjecture/sub-problem q_sub: list it in "sub_questions", TEMPORARILY ASSUME it holds, and continue the main line — every later proposition MUST then be stated as "若 <q_sub 标题> 成立,则:..." so the dependency is explicit.\n'
470
+ head += '\nIf you encounter an EXTREMELY complex auxiliary conjecture/sub-problem q_sub: list it in "sub_questions" as a PROBLEM-class object with its COMPLETE statement (every object/definition/notation it mentions must be fully defined — never quote partially, 不断章取义), together with p_{q-tmp}: a PROPOSITION-class TEMPORARY ASSUMPTION that is one possible answer to q_sub. TEMPORARILY ASSUME p_{q-tmp} holds and continue the main line — every later proposition/conclusion that depends on this assumption MUST be stated as "若 <p_{q-tmp} 的完整陈述> 成立,则:..." (with complete definitions). The scheduler registers q_sub and the problem "判断下述命题是否成立:p_{q-tmp}" in the problem list, and p_{q-tmp} in the proposition base.\n'
423
471
  head += '\nIf you obtain a COMPLETE solution: adversarially self-check (construct counterexamples, test boundary conditions) BEFORE declaring success; put the full solution text in "solution".\n'
424
472
  head += '\nRespond with ONLY a single JSON object wrapped in a ```json code fence — no prose and no braces { } outside the JSON:\n' +
425
- '{"status":"continue|success|dead-end","solution":"complete solution text, or null","solution_probability":0.85,"lemmas":[{"title":"...","statement":"...","proof":"...","细类型":{"分类名":{}},"布尔估计":0.6,"价值/关键性":0.5,"优先级":1}],"routes":[{"title":"...","progress":"...","feasibility_signal":"...","blocker":"..."}],"lessons":["..."],"survival_probability":0.5,"dead_end_reason":"... or null","sub_questions":[{"title":"...","statement":"..."}]}'
473
+ '{"status":"continue|success|dead-end","solution":"complete solution text, or null","solution_probability":0.85,"lemmas":[{"title":"...","statement":"...","proof":"...","细类型":{"分类名":{}},"布尔估计":0.6,"价值/关键性":0.5,"优先级":1}],"routes":[{"title":"...","progress":"...","feasibility_signal":"...","blocker":"..."}],"lessons":["..."],"survival_probability":0.5,"dead_end_reason":"... or null","sub_questions":[{"q_sub_title":"...","q_sub_statement":"完整问题陈述(含所有对象/定义)","assumption_title":"p_{q-tmp} 标题","assumption_statement":"完整假设陈述(含所有定义)"}]}'
426
474
  return head
427
475
  }
428
476
  function verifierReviewPrompt(r) {
@@ -431,6 +479,7 @@ export function apply(ctx) {
431
479
  else if (r.kind === 'prop-proof') target = 'PROPOSITION (id: ' + r.pId + '): ' + r.概述 + '\n' + r.side + ' PROCESS TO CHECK:\n' + r.process
432
480
  else target = 'PROBLEM (id: ' + r.qid + '): ' + r.概述 + '\nSOLUTION TO CHECK:\n' + r.process
433
481
  return verifierPersonaText() + 'You are a STRICT peer reviewer verifying one mathematical object. Check it multiple times.\n\nTARGET (r: ' + r.kind + '):\n' + target + '\n' +
482
+ knowledgeContextText() +
434
483
  capabilitiesText('verifier') +
435
484
  '\nIndependently output your initial review. Respond with ONLY a single JSON object wrapped in a ```json code fence — no prose:\n' +
436
485
  '{"Result":0.5,"Reason":"detailed logic chain, potential counterexample, or supporting evidence; when Result=1 for a bare proposition, Reason must be a complete proof; when Result=0, Reason must be a rigorous complete refutation"}'
@@ -441,6 +490,7 @@ export function apply(ctx) {
441
490
  else if (r.kind === 'prop-proof') target = 'PROPOSITION (id: ' + r.pId + '): ' + r.概述 + '\n' + r.side + ' PROCESS TO CHECK:\n' + r.process
442
491
  else target = 'PROBLEM (id: ' + r.qid + '): ' + r.概述 + '\nSOLUTION TO CHECK:\n' + r.process
443
492
  return verifierPersonaText() + 'You are one reviewer in a DEBATE ("交流群") about this object.\n\nTARGET:\n' + target + '\n' +
493
+ knowledgeContextText() +
444
494
  capabilitiesText('verifier') +
445
495
  '\nOTHERS HAVE SAID SO FAR (轮流发言):\n' + transcript + '\n' +
446
496
  '\nRespond to the others (agree / rebut / add new evidence). If you changed your Result because of them, state the reason explicitly.\n' +
@@ -514,7 +564,7 @@ export function apply(ctx) {
514
564
  let qsChanged = false
515
565
  for (let i = 0; i < qs.length; i++) {
516
566
  const q = qs[i]
517
- if (q.解法列表 && q.解法列表.some(function (s) { return s.正确概率 === 1 })) { if (!q.已解决) qsChanged = true; q.已解决 = true; q.优先级 = 'never' }
567
+ if (q.解法列表 && q.解法列表.some(function (s) { return s.正确概率 === 1 })) { if (!q.已解决) { qsChanged = true; await writeVerifiedProblemCardIfNeeded(q) } q.已解决 = true; q.优先级 = 'never' }
518
568
  }
519
569
  if (qsChanged) { await writeQs(qs); logActivity('update', 'problems marked solved by probability-1 solutions') }
520
570
  const propos = await getPropos()
@@ -595,12 +645,18 @@ export function apply(ctx) {
595
645
  if (Number(p['价值/关键性']) < Number(params.promoteValueThreshold)) continue
596
646
  if (p.在问题清单) continue
597
647
  if (qDescriptions.indexOf(p.概述) !== -1) continue
648
+ if (qDescriptions.indexOf('判断下述命题是否成立:' + p.概述) !== -1) continue
598
649
  const qid = 'q-promoted-' + String(p.id).replace(/[^a-z0-9\-]/gi, '').slice(-12)
599
- qs.push({ id: qid, 概述: p.概述, 已解决: false, 解法列表: [], 优先级: 1, progress: '由命题 ' + p.id + '(价值/关键性=' + p['价值/关键性'] + ')自动晋升;目标是证明/证伪该命题。' })
650
+ // 点3:证明/证伪列表 解法列表(条目前加【证明】/【证伪】前缀),保留概率/已验并记录来源以便回写联动
651
+ const sols = []
652
+ const proofs = p.证明列表 || []; const refutes = p.证伪列表 || []
653
+ for (let j = 0; j < proofs.length; j++) { const it = proofs[j]; sols.push({ 完整解法: '【证明】' + (it.完整过程 || ''), 正确概率: clamp01(it.正确概率 != null ? it.正确概率 : 0.5), 已验: !!it.已验, 来源: '由命题晋升(证明#' + j + ')', 来源命题: p.id, 来源列表: '证明', 来源索引: j, 验证记录: [] }) }
654
+ for (let j = 0; j < refutes.length; j++) { const it = refutes[j]; sols.push({ 完整解法: '【证伪】' + (it.完整过程 || ''), 正确概率: clamp01(it.正确概率 != null ? it.正确概率 : 0.5), 已验: !!it.已验, 来源: '由命题晋升(证伪#' + j + ')', 来源命题: p.id, 来源列表: '证伪', 来源索引: j, 验证记录: [] }) }
655
+ qs.push({ id: qid, 概述: '判断下述命题是否成立:' + p.概述, 已解决: false, 解法列表: sols, 优先级: 1, 细类型: (p.细类型 && typeof p.细类型 === 'object') ? p.细类型 : {}, '价值/关键性': p['价值/关键性'], progress: '由命题 ' + p.id + '(价值/关键性=' + p['价值/关键性'] + ')自动晋升;目标:证明或证伪该命题(解法列表中的【证明】/【证伪】条目即原命题的证明/证伪材料,验证结果会回写源命题)。' })
600
656
  p.在问题清单 = true
601
657
  await upsertProposition(p)
602
658
  await writeQs(qs)
603
- logActivity('promote', 'proposition ' + p.id + ' promoted to problem ' + qid)
659
+ logActivity('promote', 'proposition ' + p.id + ' promoted to problem ' + qid + '(' + sols.length + ' 条证明/证伪转为解法)')
604
660
  return // one per tick is enough
605
661
  }
606
662
  }
@@ -802,15 +858,31 @@ export function apply(ctx) {
802
858
  await upsertProposition(p)
803
859
  logActivity('proposition', 'lemma「' + lemma.title + '」→ ' + p.id)
804
860
  }
861
+ // 点5(q_sub 严格化):solver 报告子问题 q_sub 时,注册三个对象:
862
+ // 1) q_sub 本身(问题类,完整陈述)入 qs.json;
863
+ // 2) p_{q-tmp}(命题类临时假设:对 q_sub 的某种回答)入 Propos/;
864
+ // 3) 「判断下述命题是否成立:p_{q-tmp}」(问题类)入 qs.json。
805
865
  async function addSubQuestion(qid, dirId, sq) {
806
- if (!sq || !sq.title) return
866
+ if (!sq || !sq.q_sub_statement) return
807
867
  const qs = await getQs()
808
868
  const subId = qid + '-sub-' + shortId()
809
- qs.push({ id: subId, 概述: sq.statement || sq.title, 已解决: false, 解法列表: [], 优先级: 1, progress: '子问题:由问题 ' + qid + ' 方向 ' + dirId + ' 分支产生;主线临时假设其成立。' })
869
+ const assumeId = 'p-tmp-' + shortId()
870
+ const judgeId = qid + '-judge-' + shortId()
871
+ const assumeStatement = sq.assumption_statement || sq.assumption_title || ('对子问题「' + (sq.q_sub_title || sq.q_sub_statement) + '」的一种回答(临时假设)')
872
+ qs.push({ id: subId, 概述: sq.q_sub_statement, 已解决: false, 解法列表: [], 优先级: 1, progress: '临时子问题:由问题 ' + qid + ' 方向 ' + dirId + ' 分支产生;求解主线在 p_{q-tmp}(' + assumeId + ')假设下推进。' })
873
+ qs.push({ id: judgeId, 概述: '判断下述命题是否成立:' + assumeStatement, 已解决: false, 解法列表: [], 优先级: 1, progress: '由临时假设 p_{q-tmp}(' + assumeId + ')生成;它是对子问题 ' + subId + ' 的一种回答的命题化。' })
810
874
  await writeQs(qs)
875
+ const p = {
876
+ id: assumeId, 概述: assumeStatement, 布尔估计: 0.5,
877
+ 细类型: { 未分类: {} }, 证明列表: [], 证伪列表: [], 优先级: 1,
878
+ '价值/关键性': 0.5,
879
+ progress: '临时假设 p_{q-tmp}:由问题 ' + qid + ' 方向 ' + dirId + ' 在求解中临时假设其成立以推进主线;依赖子问题 ' + subId + ';若该假设被证伪,则依赖它的主线结论需重新审视。',
880
+ 来源问题: qid,
881
+ }
882
+ await upsertProposition(p)
811
883
  const q = qs.find(function (x) { return x.id === qid })
812
- if (q) { const prog = parseProgress(q); const d = prog.directions.find(function (x) { return x.id === dirId }); if (d) { d.sub_questions = d.sub_questions || []; d.sub_questions.push(subId) } await saveProgress(qid, prog) }
813
- logActivity('subquestion', qid + ' → ' + subId + '' + sq.title + '')
884
+ if (q) { const prog = parseProgress(q); const d = prog.directions.find(function (x) { return x.id === dirId }); if (d) { d.sub_questions = d.sub_questions || []; d.sub_questions.push({ subId: subId, judgeId: judgeId, assumeId: assumeId }) } await saveProgress(qid, prog) }
885
+ logActivity('subquestion', qid + ' → q_sub ' + subId + ' + 判断问题 ' + judgeId + ' + 临时假设 ' + assumeId)
814
886
  }
815
887
  async function addSolution(qid, solutionText, prob) {
816
888
  const qs = await getQs(); const q = qs.find(function (x) { return x.id === qid }); if (!q) return
@@ -962,7 +1034,20 @@ export function apply(ctx) {
962
1034
  sol.已验 = true
963
1035
  sol.验证记录 = sol.验证记录 || []
964
1036
  sol.验证记录.push({ 结果: v, 时间: now(), 依据: strongestReason(t, v >= 0.5 ? 1 : 0) })
965
- if (v === 1) { q.已解决 = true; q.优先级 = 'never'; await writeVerifiedProblemCardIfNeeded(q, sol) }
1037
+ // 点3 回写联动:晋升问题的解法验证结果同步回源命题的证明/证伪条目(含内容比对防错位)
1038
+ if (sol.来源命题 && (sol.来源列表 === '证明' || sol.来源列表 === '证伪')) {
1039
+ const sp = await findProposition(sol.来源命题)
1040
+ if (sp) {
1041
+ const slist = sol.来源列表 === '证明' ? (sp.证明列表 || []) : (sp.证伪列表 || [])
1042
+ const item = slist[sol.来源索引]
1043
+ if (item && item.完整过程 === String(sol.完整解法 || '').replace(/^【(证明|证伪)】/, '')) {
1044
+ item.正确概率 = v; item.已验 = true
1045
+ await upsertProposition(sp)
1046
+ logActivity('promote-sync', 'promoted solution verdict ' + v + ' synced to proposition ' + sp.id + ' ' + sol.来源列表 + '#' + sol.来源索引)
1047
+ }
1048
+ }
1049
+ }
1050
+ if (v === 1) { q.已解决 = true; q.优先级 = 'never'; await writeVerifiedProblemCardIfNeeded(q) }
966
1051
  }
967
1052
  await writeQs(qs)
968
1053
  }
@@ -979,29 +1064,41 @@ export function apply(ctx) {
979
1064
  }
980
1065
  return best
981
1066
  }
1067
+ // 点4:Verified 卡片 = 每对象一卡,内容 = 该对象当前所有正确概率=1 的证明/证伪完整过程;
1068
+ // 新 1-概率条目出现时自动更新(内容不变则不写)。幂等键 = 对象 id。
982
1069
  async function writeVerifiedCardIfNeeded(p) {
983
1070
  if (p.布尔估计 !== 1 && p.布尔估计 !== 0) return false
984
1071
  const cat = categoryOf(p)
985
1072
  const list = await readVerifiedCategory(cat)
986
- if (list.some(function (c) { return c.id === p.id })) return false // idempotent
1073
+ const idx = list.findIndex(function (c) { return c.id === p.id })
1074
+ const proofs1 = (p.证明列表 || []).filter(function (x) { return x.正确概率 === 1 })
1075
+ const refutes1 = (p.证伪列表 || []).filter(function (x) { return x.正确概率 === 1 })
1076
+ const parts = []
1077
+ for (let i = 0; i < proofs1.length; i++) parts.push('【证明 #' + (i + 1) + '】' + (proofs1[i].完整过程 || ''))
1078
+ for (let i = 0; i < refutes1.length; i++) parts.push('【证伪 #' + (i + 1) + '】' + (refutes1[i].完整过程 || ''))
987
1079
  const card = {
988
1080
  id: p.id, 概述: p.概述, 类型: '命题', 结论: p.布尔估计 === 1, 概率: p.布尔估计,
989
- 内容: (p.布尔估计 === 1 ? ((p.证明列表 || []).find(function (x) { return x.正确概率 === 1 }) || {}).完整过程 : ((p.证伪列表 || []).find(function (x) { return x.正确概率 === 1 }) || {}).完整过程) || '',
1081
+ 内容: parts.join('\n'), 证明条数: proofs1.length, 证伪条数: refutes1.length,
990
1082
  来源: p.来源问题 || '', 时间: now(), 分类: cat,
991
1083
  }
992
- list.push(card)
1084
+ if (idx === -1) list.push(card)
1085
+ else { if (list[idx].内容 === card.内容 && list[idx].概率 === card.概率) return false; list[idx] = card }
993
1086
  await writeJson('Verified/' + cat + '_Verified.json', list)
994
- return true
1087
+ return idx === -1
995
1088
  }
996
- async function writeVerifiedProblemCardIfNeeded(q, sol) {
1089
+ async function writeVerifiedProblemCardIfNeeded(q) {
997
1090
  if (!q || !q.已解决) return false
998
1091
  const cat = '问题'
999
1092
  const list = await readVerifiedCategory(cat)
1000
- if (list.some(function (c) { return c.id === q.id })) return false // idempotent
1001
- const card = { id: q.id, 概述: q.概述, 类型: '问题', 结论: true, 概率: 1, 内容: (sol && sol.完整解法) || '', 来源: q.id, 时间: now(), 分类: cat }
1002
- list.push(card)
1093
+ const idx = list.findIndex(function (c) { return c.id === q.id })
1094
+ const sols1 = (q.解法列表 || []).filter(function (s) { return s.正确概率 === 1 })
1095
+ const parts = []
1096
+ for (let i = 0; i < sols1.length; i++) parts.push('【解法 #' + (i + 1) + '】' + (sols1[i].完整解法 || ''))
1097
+ const card = { id: q.id, 概述: q.概述, 类型: '问题', 结论: true, 概率: 1, 内容: parts.join('\n'), 解法条数: sols1.length, 来源: q.id, 时间: now(), 分类: cat }
1098
+ if (idx === -1) list.push(card)
1099
+ else { if (list[idx].内容 === card.内容) return false; list[idx] = card }
1003
1100
  await writeJson('Verified/' + cat + '_Verified.json', list)
1004
- return true
1101
+ return idx === -1
1005
1102
  }
1006
1103
 
1007
1104
  // ================= child result dispatch =================
@@ -1107,7 +1204,7 @@ export function apply(ctx) {
1107
1204
  registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
1108
1205
  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() })
1109
1206
  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 } })
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 } })
1207
+ 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' }, explorerPersona: { type: 'string' }, knowledgeContext: { 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' } }, solverAllowNetwork: { type: 'boolean' }, verifierAllowNetwork: { type: 'boolean' }, solverAllowScripts: { type: 'boolean' }, verifierAllowScripts: { type: 'boolean' }, 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 } })
1111
1208
  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' } })
1112
1209
  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() })
1113
1210
  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') })
@@ -120,9 +120,12 @@
120
120
  - 本次推导出的**新引理/中间结论**及其完整证明;
121
121
  - 尝试过的各具体子路线及其进度(概述整个子路线的经历及当前进度)、可行性情况、**明确的可行性信号**(如“遇到不可消除的奇点”、“与某已知定理冲突”等)、遇到的障碍、不可行的原因等;
122
122
  - 更新对方向 `m` 的整体存活概率评估。
123
- 3. **分支递归**:若遇到**复杂度极高**的附属猜想/子问题 `q_sub`:
124
- - 可将其加入 `qs.json`(合理设置优先级等属性);
125
- - 在当前线程中,**临时假设 `q_sub` 成立**,继续推进主线。后续所得命题/结论必须形式上为 “若 `q_sub` 成立,则:...”(确保命题内包含依赖关系)。
123
+ 3. **分支递归(`q_sub` 严格化)**:若遇到**复杂度极高**的附属猜想/子问题 `q_sub`(`q_sub` 为**问题类对象**):
124
+ - `p_{q-tmp}` 为对 `q_sub` 的某种回答/答案的**临时假设**(**命题类对象**);
125
+ - 把**临时问题 `q_sub`** 与**「判断下述命题是否成立:`p_{q-tmp}`」**两个问题一起加入 `qs.json`(两者的概述、定义必须完整——所涉及的对象、依赖、环境、背景等一律给出完整定义,避免断章取义);
126
+ - 将 `p_{q-tmp}` 作为命题对象写入 `Propos/`(布尔估计记 `0.5`,`progress` 标注“临时假设 · 依赖 `q_sub`”);若该假设被证伪,则依赖它的主线结论需重新审视;
127
+ - 在当前线程中,**临时假设 `p_{q-tmp}` 成立**,继续推进主线;
128
+ - 后续所得命题/结论中**凡依赖该假设的**,必须把假设作为前提显式写出,形如「若 `p_{q-tmp}` 成立,则:...」(概述、定义完整,不断章取义)。
126
129
  4. **终止条件(进入 `END` 状态)**:
127
130
  - **成功**:得到完整的 `q` 解法,并执行严格的**自我对抗性检查**(尝试构造反例,检查边界条件)。若自检不通过,修正后重新计数迭代;
128
131
  - **失败/超时**:迭代次数达到预设上限(如 3 轮),或判定方向 `m` 已无可行路径。