dsh-vibe-math 0.3.3 → 0.3.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.
- package/README.md +1 -0
- package/package.json +1 -1
- package/vibe-math-v1/vibe-math.js +24 -3
- package/vibe-math-v2/vibe-math-v2.js +101 -33
package/README.md
CHANGED
|
@@ -420,6 +420,7 @@ flowchart TB
|
|
|
420
420
|
| `reportMode` | `file` | `file` = 写报告文件 / `push` = 推送主代理汇报 / `both` |
|
|
421
421
|
| `promoteValueThreshold` | 0.7 | Propos 中「价值/关键性」≥ 该值且未决(0,1) 的命题自动加入 qs.json |
|
|
422
422
|
| `priorityAdjust` | `none` | `none` / `deadend-deprioritize`(全死路降优先级)/ `survival-map`(按存活率重算) |
|
|
423
|
+
| `proposPriorityAdjust` | `none` | 命题优先级动态调整:`none` / `progress-graded`(按定论接近度+证明/证伪材料量重算,越接近定论越优先验证) |
|
|
423
424
|
| `provider` / `model` | 空 | 子代理模型(空 = 继承根代理) |
|
|
424
425
|
| `solverPersona` / `verifierPersona` | 空 | 注入求解器/验证器的额外要求 |
|
|
425
426
|
| `solverToolAllow` / `solverToolDeny` | `[]` | 求解器允许/禁止的工具 |
|
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
|
+
"version": "0.3.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "installer.js",
|
|
7
7
|
"exports": {
|
|
@@ -312,6 +312,19 @@ export function apply(ctx) {
|
|
|
312
312
|
async function resumeScheduler(agent) { const r = await init(agent); if (!r.ok) return r; scheduler.running = true; scheduler.gate = null; logActivity('resume', 'scheduler resumed'); await saveAll(); await maybeWriteReport(true); scheduleTick(); return { ok: true, message: 'scheduler resumed', project: currentProject, frameworkRoot: frameworkRoot() } }
|
|
313
313
|
async function pauseScheduler() { scheduler.running = false; logActivity('pause', 'scheduler paused'); await saveAll(); return { ok: true, message: 'scheduler paused' } }
|
|
314
314
|
async function abortScheduler() { scheduler.running = false; const ids = Object.keys(agentRegistry); for (let i = 0; i < ids.length; i++) await interruptChild(ids[i]); scheduler.activeCount = 0; logActivity('abort', 'scheduler aborted, ' + ids.length + ' child(ren) interrupted'); await saveAll(); return { ok: true, message: 'scheduler aborted', interrupted: ids.length } }
|
|
315
|
+
// auto 模式语义 = 无人值守自动通过关键节点:切回 auto 时把仍挂起的人工决策按自动策略放行
|
|
316
|
+
async function autoResolvePending() {
|
|
317
|
+
const pending = decisionQueue.filter(function (d) { return d.status === 'pending' })
|
|
318
|
+
for (let i = 0; i < pending.length; i++) {
|
|
319
|
+
const d = pending[i]
|
|
320
|
+
try {
|
|
321
|
+
if (d.node === 'spawn') { await spawnChild(d.data.label, d.data.promptText, d.data.meta); d.status = 'resolved'; d.resolution = { action: 'approve', auto: true } }
|
|
322
|
+
else if (d.node === 'verdict') { await settleVerdict(d.data.task, d.data.verdict); delete tasks[d.data.task.id]; d.status = 'resolved'; d.resolution = { action: 'approve', auto: true } }
|
|
323
|
+
else if (d.node === 'promote') { await promoteUnit(d.data.objId); d.status = 'resolved'; d.resolution = { action: 'approve', auto: true } }
|
|
324
|
+
} catch (e) { console.error('vibe-math: auto-resolve decision failed: ' + String((e && e.message) || e)) }
|
|
325
|
+
}
|
|
326
|
+
if (pending.length > 0) { scheduler.gate = null; logActivity('mode', 'switched to auto — auto-resolved ' + pending.length + ' pending decision(s)'); await saveAll(); scheduleTick() }
|
|
327
|
+
}
|
|
315
328
|
async function getStatus() { return { ok: true, initialized: rootAgent !== undefined, running: scheduler.running, project: currentProject, projects: await listDirsAt(vibeRoot(), 'Projects'), mode: params.mode, activeCount: scheduler.activeCount, maxParallelThreshold: params.maxParallelThreshold, frameworkRoot: frameworkRoot(), pendingDecisions: decisionQueue.filter(function (d) { return d.status === 'pending' }).length, openTasks: Object.keys(tasks).filter(function (k) { return tasks[k].status === 'spawning' || tasks[k].status === 'debating' || tasks[k].status === 'awaiting-verdict' }).length, registeredAgents: Object.keys(agentRegistry).length, recentActivity: activityLog.slice(-10), params: params } }
|
|
316
329
|
|
|
317
330
|
// ================= projects =================
|
|
@@ -344,7 +357,7 @@ export function apply(ctx) {
|
|
|
344
357
|
async function onChildEnd(info) { const meta = agentRegistry[info.id]; if (meta === undefined) return; scheduler.activeCount = Math.max(0, scheduler.activeCount - 1); const output = blocksToText(info.lastAssistantMessage); try { if (meta.role === 'brainstorm') await handleBrainstorm(info.id, meta, output); else if (meta.role === 'solver') await handleSolver(info.id, meta, output, info.stopReason); else if (meta.role === 'verifier') await handleVerifier(info.id, meta, output, info.stopReason); else if (meta.role === 'decider') await handleDecider(info.id, meta, output); else if (meta.role === 'derive') await handleDerive(info.id, meta, output) } catch (e) { console.error('vibe-math onChildEnd error: ' + String((e && e.stack) || e)) } await saveAll(); scheduleTick() }
|
|
345
358
|
async function handleBrainstorm(childId, meta, output) { delete agentRegistry[childId]; const parsed = parseJson(output); const dirs = (parsed && parsed.directions) || []; if (dirs.length === 0) { logActivity('brainstorm', 'problem ' + meta.qid + ' brainstorm returned no directions'); await saveAll(); return } brainstormRetries[meta.qid] = 0; const prog = []; for (let i = 0; i < dirs.length; i++) { const d = dirs[i]; prog.push({ direction_id: 'd_' + shortId(), title: d.title || '', method: d.method || '', core_assumption: d.core_assumption || '', round: 0, status: 'active', survival_probability: (typeof d.feasibility === 'number') ? d.feasibility : 0.5, dead_end_reason: '', lemmas: [], sub_routes: [], aux_hypotheses: [], updated_at: String(now()) }) } logActivity('brainstorm', 'problem ' + meta.qid + ' → ' + prog.length + ' directions'); await writeProgress(meta.qid, prog) }
|
|
346
359
|
async function handleDerive(childId, meta, output) { delete agentRegistry[childId]; const parsed = parseJson(output); const dirs = (parsed && parsed.directions) || []; if (dirs.length === 0) { logActivity('derive', 'problem ' + meta.qid + ' derived no new directions'); await saveAll(); return } const prog = await readProgress(meta.qid); for (let i = 0; i < dirs.length; i++) { const d = dirs[i]; prog.push({ direction_id: 'd_' + shortId(), title: d.title || '', method: d.method || '', core_assumption: d.core_assumption || (d.motivation || ''), round: 0, status: 'active', survival_probability: (typeof d.feasibility === 'number') ? d.feasibility : 0.5, dead_end_reason: '', lemmas: [], sub_routes: [], aux_hypotheses: [], updated_at: String(now()) }) } logActivity('derive', 'problem ' + meta.qid + ' derived ' + dirs.length + ' new directions'); await writeProgress(meta.qid, prog) }
|
|
347
|
-
async function handleSolver(childId, meta, output, stopReason) { const qid = meta.qid; const direction = meta.direction; const parsed = parseJson(output); const prog = await readProgress(qid); const dir = prog.find(function (d) { return d.direction_id === direction }); if (!dir) { delete agentRegistry[childId]; return } const status = (parsed && parsed.status) || statusFromStop(stopReason); dir.round = meta.round; dir.status = status; if (parsed) { if (parsed.lemmas) dir.lemmas = parsed.lemmas; if (parsed.sub_routes) dir.sub_routes = parsed.sub_routes; if (parsed.aux_hypotheses) dir.aux_hypotheses = parsed.aux_hypotheses; if (typeof parsed.survival_probability === 'number') dir.survival_probability = parsed.survival_probability; if (parsed.dead_end_reason) dir.dead_end_reason = parsed.dead_end_reason } if (status === 'success') { dir.status = 'success'; delete agentRegistry[childId]; logActivity('solver', qid + '/' + direction + ' success at round ' + meta.round); await writePending(qid, dir, parsed) } else if (status === 'dead-end' || meta.round >= params.solverMaxRounds) { dir.status = 'dead-end'; if (!dir.dead_end_reason) dir.dead_end_reason = (status === 'dead-end' && !parsed) ? 'solver ended abnormally (' + stopReason + ')' : 'iteration cap reached'; delete agentRegistry[childId]; logActivity('solver', qid + '/' + direction + ' dead-end: ' + dir.dead_end_reason) } else { const q = { id: qid, description: meta.description || '' }; await followupChild(childId, solverPrompt(q, dir, meta.round + 1)); agentRegistry[childId].round = meta.round + 1; dir.round = meta.round + 1 } if (parsed && parsed.aux_hypotheses && parsed.aux_hypotheses.length > 0) await handleAuxHypotheses(qid, parsed.aux_hypotheses); dir.updated_at = String(now()); await writeProgress(qid, prog) }
|
|
360
|
+
async function handleSolver(childId, meta, output, stopReason) { const qid = meta.qid; const direction = meta.direction; const parsed = parseJson(output); const prog = await readProgress(qid); const dir = prog.find(function (d) { return d.direction_id === direction }); if (!dir) { delete agentRegistry[childId]; return } if (!parsed && !scheduler.running) { delete agentRegistry[childId]; return } const status = (parsed && parsed.status) || statusFromStop(stopReason); dir.round = meta.round; dir.status = status; if (parsed) { if (parsed.lemmas) dir.lemmas = parsed.lemmas; if (parsed.sub_routes) dir.sub_routes = parsed.sub_routes; if (parsed.aux_hypotheses) dir.aux_hypotheses = parsed.aux_hypotheses; if (typeof parsed.survival_probability === 'number') dir.survival_probability = parsed.survival_probability; if (parsed.dead_end_reason) dir.dead_end_reason = parsed.dead_end_reason } if (status === 'success') { dir.status = 'success'; delete agentRegistry[childId]; logActivity('solver', qid + '/' + direction + ' success at round ' + meta.round); await writePending(qid, dir, parsed) } else if (status === 'dead-end' || meta.round >= params.solverMaxRounds) { dir.status = 'dead-end'; if (!dir.dead_end_reason) dir.dead_end_reason = (status === 'dead-end' && !parsed) ? 'solver ended abnormally (' + stopReason + ')' : 'iteration cap reached'; delete agentRegistry[childId]; logActivity('solver', qid + '/' + direction + ' dead-end: ' + dir.dead_end_reason) } else { const q = { id: qid, description: meta.description || '' }; await followupChild(childId, solverPrompt(q, dir, meta.round + 1)); agentRegistry[childId].round = meta.round + 1; dir.round = meta.round + 1 } if (parsed && parsed.aux_hypotheses && parsed.aux_hypotheses.length > 0) await handleAuxHypotheses(qid, parsed.aux_hypotheses); dir.updated_at = String(now()); await writeProgress(qid, prog) }
|
|
348
361
|
async function handleAuxHypotheses(qid, hyps) { const qs = await getQs(); for (let i = 0; i < hyps.length; i++) { const h = hyps[i]; if (!h || !h.title) continue; const subId = qid + '_sub_' + shortId(); qs.push({ id: subId, description: h.title + (h.statement ? ' - ' + h.statement : ''), priority: 1, status: 'unsolved', deps: [] }); dependencies[qid] = dependencies[qid] || []; dependencies[qid].push(subId); await writeQs(qs); logActivity('subquestion', qid + ' spawned sub-question ' + subId + ' (Aux_Hypothesis)') } }
|
|
349
362
|
async function writePending(qid, dir, parsed) { const doc = { qid: qid, direction: dir.direction_id, solution: solutionText(parsed, dir), lemmas: (parsed && parsed.lemmas) || [], findings: (parsed && parsed.findings) || [], sub_routes: (parsed && parsed.sub_routes) || [], aux_hypotheses: (parsed && parsed.aux_hypotheses) || [], survival_probability: dir.survival_probability, created_at: String(now()) }; const id = uuid(); await writeText('Pending_Verification/' + id + '.csv', 'qid,direction,content_json,created_at\n' + csvRow([qid, dir.direction_id, JSON.stringify(doc), String(now())]) + '\n') }
|
|
350
363
|
|
|
@@ -405,6 +418,14 @@ export function apply(ctx) {
|
|
|
405
418
|
const verdict = (parsed && parsed.verdict) || 'uncertain'
|
|
406
419
|
let t = tasks['verify:' + unitId]
|
|
407
420
|
if (!t) { t = { id: 'verify:' + unitId, type: 'verify', unitId: unitId, unit: meta.unit || { obj_id: unitId, title: unitId, content: '' }, status: 'debating', children: [], childResults: {}, round: 1, expectedCount: Math.max(3, params.verifierCount), createdAt: now() }; tasks[t.id] = t }
|
|
421
|
+
if (!parsed && !scheduler.running) {
|
|
422
|
+
// abort:被中断的验证器没有产出,丢弃该子代理并清理任务簿记(任务在 resume 时由 processVerification 重建)
|
|
423
|
+
delete agentRegistry[childId]
|
|
424
|
+
const ix = t.children.indexOf(childId); if (ix !== -1) t.children.splice(ix, 1)
|
|
425
|
+
delete t.childResults[childId]
|
|
426
|
+
if (t.children.length === 0 && t.id && tasks[t.id]) delete tasks[t.id]
|
|
427
|
+
return
|
|
428
|
+
}
|
|
408
429
|
if (t.children.indexOf(childId) === -1) t.children.push(childId)
|
|
409
430
|
t.childResults[childId] = { verdict: verdict, reason: (parsed && parsed.reason) || '', strictness: (parsed && parsed.strictness) || 'lenient', round: meta.round }
|
|
410
431
|
delete agentRegistry[childId]
|
|
@@ -481,7 +502,7 @@ export function apply(ctx) {
|
|
|
481
502
|
registerTool('vibe_math_abort', 'Abort the scheduler and interrupt all active children.', objParams({}), async function () { return await abortScheduler() })
|
|
482
503
|
registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
|
|
483
504
|
registerTool('vibe_math_report', 'Return the full progress report (status + recent activity + params) and write it to Progress_Logs/report.json.', objParams({}), async function () { await maybeWriteReport(true); return buildReport() })
|
|
484
|
-
registerTool('vibe_math_set_mode', 'Switch between manual and auto (preset) mode.', objParams({ mode: { type: 'string', enum: ['manual', 'auto'] } }, ['mode']), async function (args) { params.mode = args.mode; await saveAll(); return { ok: true, mode: params.mode } })
|
|
505
|
+
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 } })
|
|
485
506
|
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: ['direct-veto', 'weighted-vote'] }, 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' } }), async function (args) { params = Object.assign({}, params, args); await saveAll(); return { ok: true, params: params } })
|
|
486
507
|
registerTool('vibe_math_setup', 'Return the interactive parameter schema (each param: name, type, current, default, description, options, suggestion) 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' } })
|
|
487
508
|
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() })
|
|
@@ -504,7 +525,7 @@ export function apply(ctx) {
|
|
|
504
525
|
if (cmd === 'abort') return await abortScheduler()
|
|
505
526
|
if (cmd === 'status') return await getStatus()
|
|
506
527
|
if (cmd === 'report') { await maybeWriteReport(true); return buildReport() }
|
|
507
|
-
if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); return { ok: true, mode: params.mode } }
|
|
528
|
+
if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } }
|
|
508
529
|
if (cmd === 'setup') { 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' } }
|
|
509
530
|
if (cmd === 'save') return await saveSettings()
|
|
510
531
|
if (cmd === 'template') return await createTemplate(args[0] === 'project' ? 'project' : 'global')
|
|
@@ -51,6 +51,7 @@ export function apply(ctx) {
|
|
|
51
51
|
reportMode: 'file', // file | push | both
|
|
52
52
|
promoteValueThreshold: 0.7, // Propos → qs auto-promotion threshold (价值/关键性)
|
|
53
53
|
priorityAdjust: 'none', // none | deadend-deprioritize | survival-map
|
|
54
|
+
proposPriorityAdjust: 'none', // none | progress-graded(按定论接近度+证明/证伪材料量动态调命题优先级)
|
|
54
55
|
tickIntervalMs: 2000, // 调度器心跳间隔(毫秒)
|
|
55
56
|
activityLogCap: 100, // 活动日志保留条数(report.recentActivity 最多显示 30 条)
|
|
56
57
|
maxExplorerRetries: 3, // explorer 重派生上限(拆方向失败重试次数)
|
|
@@ -135,6 +136,7 @@ export function apply(ctx) {
|
|
|
135
136
|
{ name: 'reportMode', type: 'enum', options: ['file', 'push', 'both'], description: 'file = 写报告文件;push = 推送消息让主代理主动汇报;both = 两者都做', suggestion: 'file' },
|
|
136
137
|
{ name: 'promoteValueThreshold', type: 'number', description: 'Propos 中「价值/关键性」≥ 该值且未决(0,1) 的命题自动加入 qs.json', suggestion: 0.7 },
|
|
137
138
|
{ name: 'priorityAdjust', type: 'enum', options: ['none', 'deadend-deprioritize', 'survival-map'], description: '优先级动态调整策略:none=不自动调;deadend-deprioritize=方向全死路时降优先级;survival-map=按最高方向存活率重算(存活率高越优先)', suggestion: 'none' },
|
|
139
|
+
{ name: 'proposPriorityAdjust', type: 'enum', options: ['none', 'progress-graded'], description: '命题优先级动态调整:none=不自动调;progress-graded=按「定论接近度(|布尔估计-0.5|)+ 证明/证伪材料量」重算,越接近定论越优先验证', suggestion: 'none' },
|
|
138
140
|
{ name: 'tickIntervalMs', type: 'integer', description: '调度器心跳间隔(毫秒):多久扫描一次子代理状态并推进(越小越灵敏、越大越省资源)', suggestion: 2000 },
|
|
139
141
|
{ name: 'activityLogCap', type: 'integer', description: '活动日志保留条数(影响 report.recentActivity 的细节量,报告最多显示 30 条)', suggestion: 100 },
|
|
140
142
|
{ name: 'maxExplorerRetries', type: 'integer', description: 'explorer 拆方向失败的重派生上限(达到后该问题标记为方向耗尽)', suggestion: 3 },
|
|
@@ -175,6 +177,7 @@ export function apply(ctx) {
|
|
|
175
177
|
else if (k === 'verdictMode') { out[k] = (v === 'flat' || v === 'forced') ? v : DEFAULT_PARAMS[k] }
|
|
176
178
|
else if (k === 'reportMode') { out[k] = (v === 'file' || v === 'push' || v === 'both') ? v : DEFAULT_PARAMS[k] }
|
|
177
179
|
else if (k === 'priorityAdjust') { out[k] = (v === 'none' || v === 'deadend-deprioritize' || v === 'survival-map') ? v : DEFAULT_PARAMS[k] }
|
|
180
|
+
else if (k === 'proposPriorityAdjust') { out[k] = (v === 'none' || v === 'progress-graded') ? v : DEFAULT_PARAMS[k] }
|
|
178
181
|
else { out[k] = v }
|
|
179
182
|
}
|
|
180
183
|
return out
|
|
@@ -495,14 +498,15 @@ export function apply(ctx) {
|
|
|
495
498
|
}
|
|
496
499
|
// note 4: probability-1 rules
|
|
497
500
|
async function processStatusUpdates() {
|
|
498
|
-
let changed = false
|
|
499
501
|
const qs = await getQs()
|
|
502
|
+
let qsChanged = false
|
|
500
503
|
for (let i = 0; i < qs.length; i++) {
|
|
501
504
|
const q = qs[i]
|
|
502
|
-
if (q.解法列表 && q.解法列表.some(function (s) { return s.正确概率 === 1 })) { if (!q.已解决)
|
|
505
|
+
if (q.解法列表 && q.解法列表.some(function (s) { return s.正确概率 === 1 })) { if (!q.已解决) qsChanged = true; q.已解决 = true; q.优先级 = 'never' }
|
|
503
506
|
}
|
|
504
|
-
if (
|
|
507
|
+
if (qsChanged) { await writeQs(qs); logActivity('update', 'problems marked solved by probability-1 solutions') }
|
|
505
508
|
const propos = await getPropos()
|
|
509
|
+
let closedPromoted = false
|
|
506
510
|
for (let i = 0; i < propos.length; i++) {
|
|
507
511
|
const p = propos[i]
|
|
508
512
|
let pChanged = false
|
|
@@ -511,32 +515,61 @@ export function apply(ctx) {
|
|
|
511
515
|
if (proofOne && p.布尔估计 !== 1) { p.布尔估计 = 1; pChanged = true }
|
|
512
516
|
else if (refuteOne && p.布尔估计 !== 0) { p.布尔估计 = 0; pChanged = true }
|
|
513
517
|
if ((p.布尔估计 === 1 || p.布尔估计 === 0) && p.优先级 !== 'never') { p.优先级 = 'never'; pChanged = true }
|
|
514
|
-
if (p.布尔估计 === 1 || p.布尔估计 === 0) {
|
|
518
|
+
if (p.布尔估计 === 1 || p.布尔估计 === 0) {
|
|
519
|
+
if (await writeVerifiedCardIfNeeded(p)) pChanged = true
|
|
520
|
+
// 源命题已定论 → 关闭其晋升出的"僵尸"问题(避免永远未解决)
|
|
521
|
+
const srcMarker = '由命题 ' + p.id + '('
|
|
522
|
+
for (let j = 0; j < qs.length; j++) {
|
|
523
|
+
const qj = qs[j]
|
|
524
|
+
if (!qj.已解决 && String(qj.progress || '').indexOf(srcMarker) !== -1) { qj.已解决 = true; qj.优先级 = 'never'; closedPromoted = true }
|
|
525
|
+
}
|
|
526
|
+
}
|
|
515
527
|
if (pChanged) await upsertProposition(p)
|
|
516
528
|
}
|
|
529
|
+
if (closedPromoted) { await writeQs(qs); logActivity('update', 'promoted problems closed because their source proposition resolved') }
|
|
517
530
|
}
|
|
518
531
|
async function processPriorityAdjust() {
|
|
519
532
|
const mode = params.priorityAdjust || 'none'
|
|
520
|
-
if (mode
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
533
|
+
if (mode !== 'none') {
|
|
534
|
+
const qs = await getQs()
|
|
535
|
+
let changed = false
|
|
536
|
+
for (let i = 0; i < qs.length; i++) {
|
|
537
|
+
const q = qs[i]
|
|
538
|
+
if (q.已解决 || q.优先级 === 'never') continue
|
|
539
|
+
const prog = parseProgress(q)
|
|
540
|
+
if (mode === 'deadend-deprioritize') {
|
|
541
|
+
if (prog.directions.length > 0 && prog.directions.every(function (d) { return d.status === 'dead-end' })) {
|
|
542
|
+
const cur = Number(q.优先级); if (Number.isFinite(cur) && cur < 10) { q.优先级 = 10; changed = true }
|
|
543
|
+
}
|
|
544
|
+
} else if (mode === 'survival-map') {
|
|
545
|
+
if (prog.directions.length > 0) {
|
|
546
|
+
const maxSurv = Math.max.apply(null, prog.directions.map(function (d) { return Number(d.survival) || 0 }))
|
|
547
|
+
const target = Math.round(Math.max(0, Math.min(10, 10 - 10 * maxSurv)))
|
|
548
|
+
if (q.优先级 !== target) { q.优先级 = target; changed = true }
|
|
549
|
+
}
|
|
536
550
|
}
|
|
537
551
|
}
|
|
552
|
+
if (changed) { await writeQs(qs); logActivity('priority', 'priorities auto-adjusted (' + mode + ')') }
|
|
553
|
+
}
|
|
554
|
+
const pMode = params.proposPriorityAdjust || 'none'
|
|
555
|
+
if (pMode === 'progress-graded') {
|
|
556
|
+
const propos = await getPropos()
|
|
557
|
+
const changedProps = []
|
|
558
|
+
for (let i = 0; i < propos.length; i++) {
|
|
559
|
+
const p = propos[i]
|
|
560
|
+
if (p.布尔估计 === 1 || p.布尔估计 === 0 || p.优先级 === 'never') continue
|
|
561
|
+
const closeness = Math.abs(Number(p.布尔估计) - 0.5)
|
|
562
|
+
const material = Math.min(5, (p.证明列表 || []).length + (p.证伪列表 || []).length)
|
|
563
|
+
const score = closeness * 1.2 + material * 0.08
|
|
564
|
+
const target = Math.round(Math.max(0, Math.min(10, 10 - 10 * score)))
|
|
565
|
+
const cur = Number(p.优先级)
|
|
566
|
+
if (Number.isFinite(cur) && cur !== target) { p.优先级 = target; changedProps.push(p) }
|
|
567
|
+
}
|
|
568
|
+
if (changedProps.length > 0) {
|
|
569
|
+
for (let i = 0; i < changedProps.length; i++) await upsertProposition(changedProps[i])
|
|
570
|
+
logActivity('priority', 'proposition priorities auto-adjusted (progress-graded)')
|
|
571
|
+
}
|
|
538
572
|
}
|
|
539
|
-
if (changed) { await writeQs(qs); logActivity('priority', 'priorities auto-adjusted (' + mode + ')') }
|
|
540
573
|
}
|
|
541
574
|
// note 3 + user 价值 field: promote high-value unresolved propositions into qs.json
|
|
542
575
|
async function processPromote() {
|
|
@@ -583,7 +616,7 @@ export function apply(ctx) {
|
|
|
583
616
|
for (let j = 0; j < sols.length; j++) {
|
|
584
617
|
const s = sols[j]
|
|
585
618
|
if (s.正确概率 === 1 || s.正确概率 === 0 || s.已验) continue
|
|
586
|
-
out.push({ rId: 'r-' + q.id + '-s' + j, kind: 'problem-solution', qid: q.id, 概述: q.概述, process: s.完整解法 || '', idx: j, priority: q.优先级 === 'never' ? 999 : Number(q.优先级) })
|
|
619
|
+
out.push({ rId: 'r-' + q.id + '-s' + j, kind: 'problem-solution', qid: q.id, 概述: q.概述, process: s.完整解法 || '', idx: j, prob: Number(s.正确概率) || 0, priority: q.优先级 === 'never' ? 999 : Number(q.优先级) })
|
|
587
620
|
}
|
|
588
621
|
}
|
|
589
622
|
const propos = await getPropos()
|
|
@@ -592,13 +625,13 @@ export function apply(ctx) {
|
|
|
592
625
|
if (p.布尔估计 === 1 || p.布尔估计 === 0 || p.优先级 === 'never') continue
|
|
593
626
|
const proofs = p.证明列表 || []; const refutes = p.证伪列表 || []
|
|
594
627
|
if (proofs.length === 0 && refutes.length === 0) {
|
|
595
|
-
out.push({ rId: 'r-' + p.id, kind: 'proposition', pId: p.id, 概述: p.概述, priority: p.优先级 === 'never' ? 999 : Number(p.优先级) })
|
|
628
|
+
out.push({ rId: 'r-' + p.id, kind: 'proposition', pId: p.id, 概述: p.概述, prob: Number(p.布尔估计) || 0, priority: p.优先级 === 'never' ? 999 : Number(p.优先级) })
|
|
596
629
|
} else {
|
|
597
|
-
for (let j = 0; j < proofs.length; j++) { if (proofs[j].正确概率 === 1 || proofs[j].正确概率 === 0 || proofs[j].已验) continue; out.push({ rId: 'r-' + p.id + '-pf' + j, kind: 'prop-proof', pId: p.id, 概述: p.概述, side: '证明', process: proofs[j].完整过程 || '', idx: j, priority: p.优先级 === 'never' ? 999 : Number(p.优先级) }) }
|
|
598
|
-
for (let j = 0; j < refutes.length; j++) { if (refutes[j].正确概率 === 1 || refutes[j].正确概率 === 0 || refutes[j].已验) continue; out.push({ rId: 'r-' + p.id + '-rf' + j, kind: 'prop-proof', pId: p.id, 概述: p.概述, side: '证伪', process: refutes[j].完整过程 || '', idx: j, priority: p.优先级 === 'never' ? 999 : Number(p.优先级) }) }
|
|
630
|
+
for (let j = 0; j < proofs.length; j++) { if (proofs[j].正确概率 === 1 || proofs[j].正确概率 === 0 || proofs[j].已验) continue; out.push({ rId: 'r-' + p.id + '-pf' + j, kind: 'prop-proof', pId: p.id, 概述: p.概述, side: '证明', process: proofs[j].完整过程 || '', idx: j, prob: Number(proofs[j].正确概率) || 0, priority: p.优先级 === 'never' ? 999 : Number(p.优先级) }) }
|
|
631
|
+
for (let j = 0; j < refutes.length; j++) { if (refutes[j].正确概率 === 1 || refutes[j].正确概率 === 0 || refutes[j].已验) continue; out.push({ rId: 'r-' + p.id + '-rf' + j, kind: 'prop-proof', pId: p.id, 概述: p.概述, side: '证伪', process: refutes[j].完整过程 || '', idx: j, prob: Number(refutes[j].正确概率) || 0, priority: p.优先级 === 'never' ? 999 : Number(p.优先级) }) }
|
|
599
632
|
}
|
|
600
633
|
}
|
|
601
|
-
out.sort(function (a, b) { return a.priority - b.priority })
|
|
634
|
+
out.sort(function (a, b) { if (a.priority !== b.priority) return a.priority - b.priority; return (b.prob || 0) - (a.prob || 0) })
|
|
602
635
|
return out
|
|
603
636
|
}
|
|
604
637
|
async function backfillVerifiers(t) {
|
|
@@ -686,6 +719,7 @@ export function apply(ctx) {
|
|
|
686
719
|
const prog = parseProgress(q)
|
|
687
720
|
const dir = prog.directions.find(function (d) { return d.id === dirId })
|
|
688
721
|
if (!dir) { delete agentRegistry[childId]; return }
|
|
722
|
+
if (!parsed && !scheduler.running) { delete agentRegistry[childId]; return } // abort:不把方向标记为死路,保留待 resume
|
|
689
723
|
const status = (parsed && parsed.status) || statusFromStop(stopReason)
|
|
690
724
|
dir.round = meta.round
|
|
691
725
|
if (parsed) {
|
|
@@ -742,9 +776,11 @@ export function apply(ctx) {
|
|
|
742
776
|
function statusFromStop(stopReason) { return (stopReason === 'completed' || stopReason === 'max-tokens') ? 'continue' : 'dead-end' }
|
|
743
777
|
async function addLemmaAsProposition(qid, lemma) {
|
|
744
778
|
if (!lemma || !lemma.title) return
|
|
779
|
+
let be = clamp01(lemma.布尔估计 != null ? lemma.布尔估计 : 0.6)
|
|
780
|
+
if (be >= 1) be = 0.99; else if (be <= 0) be = 0.01 // 写入时概率必须 <1 且 >0(待验证器验证)
|
|
745
781
|
const p = {
|
|
746
782
|
id: 'p-' + shortId(), 概述: lemma.statement || lemma.title,
|
|
747
|
-
布尔估计:
|
|
783
|
+
布尔估计: be,
|
|
748
784
|
细类型: (lemma.细类型 && typeof lemma.细类型 === 'object') ? lemma.细类型 : { 未分类: {} },
|
|
749
785
|
证明列表: [{ 完整过程: lemma.proof || '', 正确概率: clamp01(0.7), '支持信息/依据': '' }],
|
|
750
786
|
证伪列表: [], 优先级: (lemma.优先级 != null) ? lemma.优先级 : 1,
|
|
@@ -785,6 +821,14 @@ export function apply(ctx) {
|
|
|
785
821
|
const Reason = (parsed && parsed.Reason) || ''
|
|
786
822
|
let t = tasks['verify:' + rId]
|
|
787
823
|
if (!t) { t = { id: 'verify:' + rId, type: 'verify', r: { kind: 'proposition', pId: rId, 概述: rId }, rId: rId, status: 'debating', children: [], childResults: {}, round: 1, expectedCount: Math.max(2, params.verifierCount), createdAt: now() }; tasks[t.id] = t }
|
|
824
|
+
if (!parsed && !scheduler.running) {
|
|
825
|
+
// abort:被中断的验证器没有产出,丢弃该子代理并清理任务簿记(任务在 resume 时由 processVerify 重建)
|
|
826
|
+
delete agentRegistry[childId]
|
|
827
|
+
const ix = t.children.indexOf(childId); if (ix !== -1) t.children.splice(ix, 1)
|
|
828
|
+
delete t.childResults[childId]
|
|
829
|
+
if (t.children.length === 0 && t.id && tasks[t.id]) delete tasks[t.id]
|
|
830
|
+
return
|
|
831
|
+
}
|
|
788
832
|
if (t.children.indexOf(childId) === -1) t.children.push(childId)
|
|
789
833
|
t.childResults[childId] = { Result: Result, Reason: Reason, round: meta.round }
|
|
790
834
|
delete agentRegistry[childId]
|
|
@@ -796,6 +840,7 @@ export function apply(ctx) {
|
|
|
796
840
|
async function advanceVerification(t, round) {
|
|
797
841
|
if (round < params.debateMaxRounds && !consensus(t) && t.children.length > 0) {
|
|
798
842
|
if (!scheduler.running) { t.status = 'paused'; return } // resume will re-advance this task
|
|
843
|
+
if (scheduler.activeCount >= params.maxParallelThreshold) { t.status = 'paused'; return } // 并发门:等有空闲槽位再辩论(reconcileVerify 会重推进)
|
|
799
844
|
t.round = round + 1
|
|
800
845
|
const transcript = buildTranscript(t)
|
|
801
846
|
const nextChildren = []
|
|
@@ -905,7 +950,7 @@ export function apply(ctx) {
|
|
|
905
950
|
sol.已验 = true
|
|
906
951
|
sol.验证记录 = sol.验证记录 || []
|
|
907
952
|
sol.验证记录.push({ 结果: v, 时间: now(), 依据: strongestReason(t, v >= 0.5 ? 1 : 0) })
|
|
908
|
-
if (v === 1) { q.已解决 = true; q.优先级 = 'never' }
|
|
953
|
+
if (v === 1) { q.已解决 = true; q.优先级 = 'never'; await writeVerifiedProblemCardIfNeeded(q, sol) }
|
|
909
954
|
}
|
|
910
955
|
await writeQs(qs)
|
|
911
956
|
}
|
|
@@ -936,6 +981,16 @@ export function apply(ctx) {
|
|
|
936
981
|
await writeJson('Verified/' + cat + '_Verified.json', list)
|
|
937
982
|
return true
|
|
938
983
|
}
|
|
984
|
+
async function writeVerifiedProblemCardIfNeeded(q, sol) {
|
|
985
|
+
if (!q || !q.已解决) return false
|
|
986
|
+
const cat = '问题'
|
|
987
|
+
const list = await readVerifiedCategory(cat)
|
|
988
|
+
if (list.some(function (c) { return c.id === q.id })) return false // idempotent
|
|
989
|
+
const card = { id: q.id, 概述: q.概述, 类型: '问题', 结论: true, 概率: 1, 内容: (sol && sol.完整解法) || '', 来源: q.id, 时间: now(), 分类: cat }
|
|
990
|
+
list.push(card)
|
|
991
|
+
await writeJson('Verified/' + cat + '_Verified.json', list)
|
|
992
|
+
return true
|
|
993
|
+
}
|
|
939
994
|
|
|
940
995
|
// ================= child result dispatch =================
|
|
941
996
|
async function onChildEnd(info) {
|
|
@@ -970,15 +1025,28 @@ export function apply(ctx) {
|
|
|
970
1025
|
logActivity(fresh ? 'start' : 'resume', 'cleared ' + Object.keys(agentRegistry).length + ' agent(s) and ' + Object.keys(tasks).length + ' task(s) (' + (fresh ? 'restart' : 'stale from previous process') + ')')
|
|
971
1026
|
agentRegistry = {}; tasks = {}
|
|
972
1027
|
}
|
|
1028
|
+
scheduler.activeCount = 0 // 仅清空 registry/tasks 时归零;同进程 resume 保留存活计数(并发门才准确)
|
|
973
1029
|
}
|
|
974
1030
|
await writeJson('VibeMath_State/process_epoch.json', processEpoch)
|
|
975
|
-
|
|
1031
|
+
await saveAll()
|
|
976
1032
|
return { ok: true }
|
|
977
1033
|
}
|
|
978
1034
|
async function startScheduler(agent) { const r = await init(agent, true); if (!r.ok) return r; scheduler.running = true; scheduler.startedAt = now(); scheduler.gate = null; logActivity('start', 'scheduler started for project ' + currentProject); await saveAll(); await maybeWriteReport(true); scheduleTick(); return { ok: true, message: 'scheduler started', project: currentProject, frameworkRoot: frameworkRoot() } }
|
|
979
1035
|
async function resumeScheduler(agent) { const r = await init(agent, false); if (!r.ok) return r; scheduler.running = true; scheduler.gate = null; logActivity('resume', 'scheduler resumed'); await saveAll(); await maybeWriteReport(true); scheduleTick(); return { ok: true, message: 'scheduler resumed', project: currentProject, frameworkRoot: frameworkRoot() } }
|
|
980
1036
|
async function pauseScheduler() { scheduler.running = false; logActivity('pause', 'scheduler paused'); await saveAll(); return { ok: true, message: 'scheduler paused' } }
|
|
981
1037
|
async function abortScheduler() { scheduler.running = false; const ids = Object.keys(agentRegistry); for (let i = 0; i < ids.length; i++) await interruptChild(ids[i]); scheduler.activeCount = 0; logActivity('abort', 'scheduler aborted, ' + ids.length + ' child(ren) interrupted'); await saveAll(); return { ok: true, message: 'scheduler aborted', interrupted: ids.length } }
|
|
1038
|
+
// auto 模式语义 = 无人值守自动通过关键节点:切回 auto 时把仍挂起的人工决策按自动策略放行
|
|
1039
|
+
async function autoResolvePending() {
|
|
1040
|
+
const pending = decisionQueue.filter(function (d) { return d.status === 'pending' })
|
|
1041
|
+
for (let i = 0; i < pending.length; i++) {
|
|
1042
|
+
const d = pending[i]
|
|
1043
|
+
try {
|
|
1044
|
+
if (d.node === 'spawn') { await spawnChild(d.data.label, d.data.promptText, d.data.meta); d.status = 'resolved'; d.resolution = { action: 'approve', auto: true } }
|
|
1045
|
+
else if (d.node === 'verdict') { await settleVerdict(d.data.task, d.data.verdict); delete tasks[d.data.task.id]; d.status = 'resolved'; d.resolution = { action: 'approve', auto: true } }
|
|
1046
|
+
} catch (e) { console.error('vibe-math-v2: auto-resolve decision failed: ' + String((e && e.message) || e)) }
|
|
1047
|
+
}
|
|
1048
|
+
if (pending.length > 0) { scheduler.gate = null; logActivity('mode', 'switched to auto — auto-resolved ' + pending.length + ' pending decision(s)'); await saveAll(); scheduleTick() }
|
|
1049
|
+
}
|
|
982
1050
|
async function getStatus() {
|
|
983
1051
|
const qs = await getQs(); const propos = await getPropos()
|
|
984
1052
|
return {
|
|
@@ -990,7 +1058,7 @@ export function apply(ctx) {
|
|
|
990
1058
|
propositions: { total: propos.length, resolved: propos.filter(function (p) { return p.布尔估计 === 1 || p.布尔估计 === 0 }).length },
|
|
991
1059
|
pendingDecisions: decisionQueue.filter(function (d) { return d.status === 'pending' }).length,
|
|
992
1060
|
registeredAgents: Object.keys(agentRegistry).length,
|
|
993
|
-
recentActivity: activityLog.slice(-10), params: params,
|
|
1061
|
+
recentActivity: activityLog.slice(-Math.min(10, Number(params.activityLogCap) || 100)), params: params,
|
|
994
1062
|
}
|
|
995
1063
|
}
|
|
996
1064
|
|
|
@@ -1026,8 +1094,8 @@ export function apply(ctx) {
|
|
|
1026
1094
|
registerTool('vibe_math_abort', 'Abort the scheduler and interrupt all active children.', objParams({}), async function () { return await abortScheduler() })
|
|
1027
1095
|
registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
|
|
1028
1096
|
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() })
|
|
1029
|
-
registerTool('vibe_math_set_mode', 'Switch between manual and auto (preset) mode.', objParams({ mode: { type: 'string', enum: ['manual', 'auto'] } }, ['mode']), async function (args) { params.mode = args.mode; await saveAll(); return { ok: true, mode: params.mode } })
|
|
1030
|
-
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'] }, 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 } })
|
|
1097
|
+
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 } })
|
|
1031
1099
|
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' } })
|
|
1032
1100
|
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() })
|
|
1033
1101
|
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') })
|
|
@@ -1054,7 +1122,7 @@ export function apply(ctx) {
|
|
|
1054
1122
|
if (cmd === 'abort') return await abortScheduler()
|
|
1055
1123
|
if (cmd === 'status') return await getStatus()
|
|
1056
1124
|
if (cmd === 'report') { await maybeWriteReport(true); return await buildReport() }
|
|
1057
|
-
if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); return { ok: true, mode: params.mode } }
|
|
1125
|
+
if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } }
|
|
1058
1126
|
if (cmd === 'setup') { 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' } }
|
|
1059
1127
|
if (cmd === 'save') return await saveSettings()
|
|
1060
1128
|
if (cmd === 'template') return await createTemplate(args[0] === 'project' ? 'project' : 'global')
|