dsh-vibe-math 0.3.13 → 0.3.14

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
@@ -237,6 +237,8 @@ dsh plugin --profile <你的 profile> add github:ChongCyrus/Vibe-Mathematics
237
237
  - **生成模板**:`/vibe template`(生成到工作区)或 `/vibe template project`(生成到当前项目)——
238
238
  会产出一份**带 `//` 注释、逐项中文说明**的 JSON 模板,你手改后重启/resume 即生效。
239
239
  - **保存当前值**:`/vibe save` 把当前生效参数写回该文件。
240
+ - **唯一持久化来源**:该文件是参数的**唯一持久化层**(项目级优先 → 缺失时回退全局 `<工作区>/VibeMath/vibe_math_setting.json` → 内置默认)。
241
+ `vibe_math_set_params` / `set_mode` 会**立即写回**项目级文件并持久化,无需再手动 save。
240
242
 
241
243
  ---
242
244
 
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.13",
4
+ "version": "0.3.14",
5
5
  "type": "module",
6
6
  "main": "installer.js",
7
7
  "exports": {
@@ -212,7 +212,7 @@ export function apply(ctx) {
212
212
  lines.push('{')
213
213
  lines.push(' // Vibe Math 默认参数配置(JSON with Comments,可加 // 注释)。')
214
214
  lines.push(' // 位置:<项目>/vibe_math_setting.json(全局回退:<工作区>/VibeMath/vibe_math_setting.json)。')
215
- lines.push(' // 该文件只提供“默认值”;运行期 vibe_math_set_params 改过的值会存到 VibeMath_State/params.json 并覆盖此处。')
215
+ lines.push(' // 本文件是参数的唯一持久化来源:vibe_math_set_params / set_mode 会立即写回此文件;全局文件仅作项目文件不存在时的回退默认。')
216
216
  const keys = Object.keys(src).sort()
217
217
  for (let i = 0; i < keys.length; i++) {
218
218
  const k = keys[i]
@@ -231,8 +231,20 @@ export function apply(ctx) {
231
231
  async function createTemplate(where) { const isGlobal = where !== 'project'; const path = isGlobal ? (vibeRoot() + '/vibe_math_setting.json') : (frameworkRoot() + '/vibe_math_setting.json'); const content = settingsTemplateFrom(DEFAULT_PARAMS); const ok = isGlobal ? await writeTextAbs(path, content) : await writeText('vibe_math_setting.json', content); return { ok: ok, path: path, where: isGlobal ? 'global' : 'project' } }
232
232
 
233
233
  // ================= persistence =================
234
- async function loadState() { const pj = await readJson('VibeMath_State/params.json'); if (pj) params = Object.assign({}, params, pj); const s = await readJson('VibeMath_State/scheduler_state.json'); if (s) scheduler = Object.assign({}, scheduler, s); const r = await readJson('VibeMath_State/agent_registry.json'); if (r) agentRegistry = r; const d = await readJson('VibeMath_State/dependencies.json'); if (d) dependencies = d; const dq = await readJson('VibeMath_State/decision_queue.json'); if (dq) decisionQueue = dq; const tk = await readJson('VibeMath_State/tasks.json'); if (tk) tasks = tk; const sv = await readJson('VibeMath_State/solved_by_verified.json'); if (sv) solvedByVerified = sv; const pq = await readJson('VibeMath_State/promotion_queue.json'); if (pq) promotionQueue = pq; const va = await readJson('VibeMath_State/verifier_accuracy.json'); if (va) verifierAccuracy = va }
235
- async function saveAll() { await writeJson('VibeMath_State/params.json', params); await writeJson('VibeMath_State/scheduler_state.json', scheduler); await writeJson('VibeMath_State/agent_registry.json', agentRegistry); await writeJson('VibeMath_State/dependencies.json', dependencies); await writeJson('VibeMath_State/decision_queue.json', decisionQueue); await writeJson('VibeMath_State/tasks.json', tasks); await writeJson('VibeMath_State/solved_by_verified.json', solvedByVerified); await writeJson('VibeMath_State/promotion_queue.json', promotionQueue); await writeJson('VibeMath_State/verifier_accuracy.json', verifierAccuracy); scheduler.lastCheckpoint = now() }
234
+ async function loadState() { const s = await readJson('VibeMath_State/scheduler_state.json'); if (s) scheduler = Object.assign({}, scheduler, s); const r = await readJson('VibeMath_State/agent_registry.json'); if (r) agentRegistry = r; const d = await readJson('VibeMath_State/dependencies.json'); if (d) dependencies = d; const dq = await readJson('VibeMath_State/decision_queue.json'); if (dq) decisionQueue = dq; const tk = await readJson('VibeMath_State/tasks.json'); if (tk) tasks = tk; const sv = await readJson('VibeMath_State/solved_by_verified.json'); if (sv) solvedByVerified = sv; const pq = await readJson('VibeMath_State/promotion_queue.json'); if (pq) promotionQueue = pq; const va = await readJson('VibeMath_State/verifier_accuracy.json'); if (va) verifierAccuracy = va }
235
+ async function saveAll() { await writeJson('VibeMath_State/scheduler_state.json', scheduler); await writeJson('VibeMath_State/agent_registry.json', agentRegistry); await writeJson('VibeMath_State/dependencies.json', dependencies); await writeJson('VibeMath_State/decision_queue.json', decisionQueue); await writeJson('VibeMath_State/tasks.json', tasks); await writeJson('VibeMath_State/solved_by_verified.json', solvedByVerified); await writeJson('VibeMath_State/promotion_queue.json', promotionQueue); await writeJson('VibeMath_State/verifier_accuracy.json', verifierAccuracy); scheduler.lastCheckpoint = now() }
236
+ // 一次性迁移(单文件化):旧版 params.json 合并进 vibe_math_setting.json 后删除。
237
+ async function migrateLegacyParams() {
238
+ const legacy = await readJson('VibeMath_State/params.json')
239
+ if (!legacy || Object.keys(legacy).length === 0) return
240
+ try {
241
+ params = Object.assign({}, params, sanitizeParams(legacy))
242
+ await saveSettings()
243
+ await writeJson('VibeMath_State/params.json', {}) // 一次性守卫:即使删除失败,空对象也不再覆盖设置文件
244
+ await removeFile('VibeMath_State/params.json')
245
+ logActivity('params', 'legacy params.json merged into vibe_math_setting.json and removed')
246
+ } catch (e) { console.error('vibe-math: params migration failed: ' + String((e && e.message) || e)) }
247
+ }
236
248
 
237
249
  // ================= activity log / report =================
238
250
  function logActivity(event, detail) { activityLog.push({ at: now(), event: event, detail: String(detail || '') }); const cap = Number(params.activityLogCap) || 100; if (activityLog.length > cap) activityLog.shift(); reportDirty = true }
@@ -307,7 +319,7 @@ export function apply(ctx) {
307
319
 
308
320
  // ================= init / control =================
309
321
  async function resolveRootAgent(agent) { if (rootAgent) return rootAgent; if (agent) { rootAgent = agent; return rootAgent } try { const roots = agents.roots ? agents.roots() : []; if (roots && roots.length > 0) { rootAgent = roots[0]; return rootAgent } } catch (e) {} return rootAgent }
310
- async function init(agent) { await resolveRootAgent(agent); if (!rootAgent) return { ok: false, message: 'no root agent available' }; currentProject = await readCurrentProject(); await ensureDirs(); if ((await readText('qs/qs.csv')) === undefined) await writeText('qs/qs.csv', 'id,description,priority,status,deps\n'); params = Object.assign({}, DEFAULT_PARAMS); await loadSettings(); await loadState(); scheduler.activeCount = 0; await saveAll(); return { ok: true } }
322
+ async function init(agent) { await resolveRootAgent(agent); if (!rootAgent) return { ok: false, message: 'no root agent available' }; currentProject = await readCurrentProject(); await ensureDirs(); if ((await readText('qs/qs.csv')) === undefined) await writeText('qs/qs.csv', 'id,description,priority,status,deps\n'); params = Object.assign({}, DEFAULT_PARAMS); await loadSettings(); await migrateLegacyParams(); await loadState(); scheduler.activeCount = 0; await saveAll(); return { ok: true } }
311
323
  async function startScheduler(agent) { const r = await init(agent); 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() } }
312
324
  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
325
  async function pauseScheduler() { scheduler.running = false; logActivity('pause', 'scheduler paused'); await saveAll(); return { ok: true, message: 'scheduler paused' } }
@@ -338,7 +350,7 @@ export function apply(ctx) {
338
350
  await ensureDirs()
339
351
  if ((await readText('qs/qs.csv')) === undefined) await writeText('qs/qs.csv', 'id,description,priority,status,deps\n')
340
352
  params = Object.assign({}, DEFAULT_PARAMS); scheduler = { running: false, activeCount: 0, startedAt: 0, lastCheckpoint: 0, gate: null }; agentRegistry = {}; dependencies = {}; decisionQueue = []; tasks = {}; brainstormRetries = {}; deriveRetries = {}; solvedByVerified = {}; promotionQueue = {}; verifierAccuracy = {}; activityLog = []
341
- await loadSettings(); await loadState(); await saveAll()
353
+ await loadSettings(); await migrateLegacyParams(); await loadState(); await saveAll()
342
354
  return { ok: true, project: slug, frameworkRoot: frameworkRoot() }
343
355
  }
344
356
 
@@ -508,8 +520,8 @@ export function apply(ctx) {
508
520
  registerTool('vibe_math_abort', 'Abort the scheduler and interrupt all active children.', objParams({}), async function () { return await abortScheduler() })
509
521
  registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
510
522
  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() })
511
- 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 } })
512
- 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 } })
523
+ 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(); await saveSettings(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } })
524
+ 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(); await saveSettings(); return { ok: true, params: params } })
513
525
  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' } })
514
526
  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() })
515
527
  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') })
@@ -531,7 +543,7 @@ export function apply(ctx) {
531
543
  if (cmd === 'abort') return await abortScheduler()
532
544
  if (cmd === 'status') return await getStatus()
533
545
  if (cmd === 'report') { await maybeWriteReport(true); return buildReport() }
534
- if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } }
546
+ if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); await saveSettings(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } }
535
547
  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' } }
536
548
  if (cmd === 'save') return await saveSettings()
537
549
  if (cmd === 'template') return await createTemplate(args[0] === 'project' ? 'project' : 'global')
@@ -214,6 +214,7 @@ export function apply(ctx) {
214
214
  lines.push('{')
215
215
  lines.push(' // Vibe Math V2 默认参数配置(JSON with Comments,可加 // 注释)。')
216
216
  lines.push(' // 位置:<项目>/vibe_math_setting.json(全局回退:<工作区>/VibeMath/vibe_math_setting.json)。')
217
+ lines.push(' // 本文件是参数的唯一持久化来源:vibe_math_set_params / set_mode 会立即写回此文件;全局文件仅作项目文件不存在时的回退默认。')
217
218
  const keys = Object.keys(src).sort()
218
219
  for (let i = 0; i < keys.length; i++) {
219
220
  const k = keys[i]
@@ -233,7 +234,6 @@ export function apply(ctx) {
233
234
 
234
235
  // ================= persistence =================
235
236
  async function loadState() {
236
- const pj = await readJson('VibeMath_State/params.json'); if (pj) params = Object.assign({}, params, pj)
237
237
  const s = await readJson('VibeMath_State/scheduler_state.json'); if (s) scheduler = Object.assign({}, scheduler, s)
238
238
  const r = await readJson('VibeMath_State/agent_registry.json'); if (r) agentRegistry = r
239
239
  const dq = await readJson('VibeMath_State/decision_queue.json'); if (dq) decisionQueue = dq
@@ -242,7 +242,6 @@ export function apply(ctx) {
242
242
  const er = await readJson('VibeMath_State/explorer_retries.json'); if (er) explorerRetries = er
243
243
  }
244
244
  async function saveAll() {
245
- await writeJson('VibeMath_State/params.json', params)
246
245
  await writeJson('VibeMath_State/scheduler_state.json', scheduler)
247
246
  await writeJson('VibeMath_State/agent_registry.json', agentRegistry)
248
247
  await writeJson('VibeMath_State/decision_queue.json', decisionQueue)
@@ -251,6 +250,18 @@ export function apply(ctx) {
251
250
  await writeJson('VibeMath_State/explorer_retries.json', explorerRetries)
252
251
  scheduler.lastCheckpoint = now()
253
252
  }
253
+ // 一次性迁移(单文件化):旧版 VibeMath_State/params.json 中的运行时参数合并进 vibe_math_setting.json 后删除。
254
+ async function migrateLegacyParams() {
255
+ const legacy = await readJson('VibeMath_State/params.json')
256
+ if (!legacy || Object.keys(legacy).length === 0) return
257
+ try {
258
+ params = Object.assign({}, params, sanitizeParams(legacy))
259
+ await saveSettings()
260
+ await writeJson('VibeMath_State/params.json', {}) // 一次性守卫:即使删除失败,空对象也不再覆盖设置文件
261
+ await removeFile('VibeMath_State/params.json')
262
+ logActivity('params', 'legacy params.json merged into vibe_math_setting.json and removed')
263
+ } catch (e) { console.error('vibe-math-v2: params migration failed: ' + String((e && e.message) || e)) }
264
+ }
254
265
 
255
266
  // ================= data layer: qs.json =================
256
267
  async function getQs() { const a = await readJson('qs/qs.json'); return Array.isArray(a) ? a : [] }
@@ -1159,7 +1170,7 @@ export function apply(ctx) {
1159
1170
  await resolveRootAgent(agent); if (!rootAgent) return { ok: false, message: 'no root agent available' }
1160
1171
  currentProject = await readCurrentProject(); await ensureDirs()
1161
1172
  if ((await readJson('qs/qs.json')) === undefined) await writeJson('qs/qs.json', [])
1162
- params = Object.assign({}, DEFAULT_PARAMS); await loadSettings(); await loadState()
1173
+ params = Object.assign({}, DEFAULT_PARAMS); await loadSettings(); await migrateLegacyParams(); await loadState()
1163
1174
  // Distinguish same-process continue from cross-process restart via processEpoch:
1164
1175
  // equal epoch = same process (pause→resume; children may still be alive), different
1165
1176
  // epoch = previous process wrote this state (in-flight children are gone).
@@ -1217,7 +1228,7 @@ export function apply(ctx) {
1217
1228
  currentProject = slug; await writeCurrentProject(); await ensureDirs()
1218
1229
  if ((await readJson('qs/qs.json')) === undefined) await writeJson('qs/qs.json', [])
1219
1230
  params = Object.assign({}, DEFAULT_PARAMS); scheduler = { running: false, activeCount: 0, startedAt: 0, lastCheckpoint: 0, gate: null }; agentRegistry = {}; decisionQueue = []; verifierAccuracy = {}; tasks = {}; explorerRetries = {}; activityLog = []; lastReportWrite = 0; lastPushReport = 0; reportDirty = false
1220
- await loadSettings(); await loadState(); await saveAll()
1231
+ await loadSettings(); await migrateLegacyParams(); await loadState(); await saveAll()
1221
1232
  return { ok: true, project: slug, frameworkRoot: frameworkRoot() }
1222
1233
  }
1223
1234
 
@@ -1240,8 +1251,8 @@ export function apply(ctx) {
1240
1251
  registerTool('vibe_math_abort', 'Abort the scheduler and interrupt all active children.', objParams({}), async function () { return await abortScheduler() })
1241
1252
  registerTool('vibe_math_status', 'Show scheduler status, params, active agents, projects, and recent activity.', objParams({}), async function () { return await getStatus() })
1242
1253
  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() })
1243
- 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 } })
1244
- 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 } })
1254
+ 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(); await saveSettings(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } })
1255
+ 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(); await saveSettings(); return { ok: true, params: params } })
1245
1256
  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' } })
1246
1257
  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() })
1247
1258
  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') })
@@ -1268,7 +1279,7 @@ export function apply(ctx) {
1268
1279
  if (cmd === 'abort') return await abortScheduler()
1269
1280
  if (cmd === 'status') return await getStatus()
1270
1281
  if (cmd === 'report') { await maybeWriteReport(true); return await buildReport() }
1271
- if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } }
1282
+ if (cmd === 'mode') { params.mode = (args[0] === 'manual') ? 'manual' : 'auto'; await saveAll(); await saveSettings(); if (params.mode === 'auto') await autoResolvePending(); return { ok: true, mode: params.mode } }
1272
1283
  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' } }
1273
1284
  if (cmd === 'save') return await saveSettings()
1274
1285
  if (cmd === 'template') return await createTemplate(args[0] === 'project' ? 'project' : 'global')