dsh-vibe-math 2.0.10 → 2.0.12

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/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 — THREE agent presets in one install: vibe-math-v2 (probability-driven: qs.json + Propos knowledge base + explorer→solver→review/debate verdict), vibe-math-v3 (THIRD-generation, recommended: paper-style Markdown knowledge base with Problems/Progress/Propos/Methods/Verified + planner-agent scheduling that decides the next N actions + universal theory/method invention library + agents write their own Markdown directly via a per-file write lock), and vibe-math-v4 (FOURTH-generation: persistent self-organizing resident subagents that message & meet to decide all tasks, verify only by unanimous consensus, /compact at a context threshold, and stop only when all agree the problem is solved). Installing this bundle auto-installs all three presets (v1 was removed at v2.0.0).",
4
- "version": "2.0.10",
4
+ "version": "2.0.12",
5
5
  "type": "module",
6
6
  "engines": {
7
7
  "node": "^22.19.0 || >=24.0.0"
@@ -253,7 +253,7 @@ export function apply(ctx) {
253
253
  residents.set(r.rId,r); await saveAll(); logActivity('spawn',r.rId+' ('+(r.direction||'brainstorm')+')')
254
254
  }
255
255
  async function wakeResident(r, promptText, kind){
256
- if(!r.childId) return false
256
+ if(!r || !r.childId) return false // a removed resident must never be woken (rune: crash on r.childId)
257
257
  clearHeartbeat()
258
258
  busy.add(r.rId); wakeKind.set(r.rId,kind||'normal'); currentResident=r.rId
259
259
  r.lastActiveAt=now(); r.rounds+=1; r.roundsSinceCompact+=1
@@ -305,7 +305,7 @@ export function apply(ctx) {
305
305
  async function recordMethod(rId,o){ const id=o.id||('m-'+shortId()); const lines=['# 方法|'+(o.title||id),'- 标题: '+(o.title||id),'- ID: '+id,'- 类型: '+(o.type||'方法'),'- 状态: 经验','- 可信断言: []','- 价值程度: '+cl(o.value!=null?o.value:0.5),'- 动机用途计划: '+(o.motivation||''),'','## 核心内容',String(o.content||''),'','## 定义与记号',String(o.notation||''),'','## 应用记录','## 改进历史','']; await writeText('Methods/'+rId+'/'+id+'.md',lines.join('\n')); logActivity('record',rId+' 方法 '+id); bumpArtifacts(); return {ok:true,id,file:'Methods/'+rId+'/'+id+'.md'} }
306
306
  async function recordSubproblem(rId,o){ const id=o.id||('s-'+shortId()); const lines=['# 子问题|'+(o.title||id),'- 标题: '+(o.title||id),'- ID: '+id,'- 状态: 求解中','- 价值程度: '+cl(o.value!=null?o.value:0.5),'- 动机用途计划: '+(o.motivation||''),'- 依赖: []','','## 陈述',String(o.statement||''),'','## 进度','']; await writeText('Subproblems/'+rId+'/'+id+'.md',lines.join('\n')); logActivity('record',rId+' 子问题 '+id); bumpArtifacts(); return {ok:true,id,file:'Subproblems/'+rId+'/'+id+'.md'} }
307
307
  // auto-sync meeting: every meetingKeepEvery new artifacts, convene a general coordination meeting
308
- function bumpArtifacts(){ artifactCount+=1; markProgress(); if(!meetingState && !verifyState && Number(params.meetingKeepEvery)>0 && artifactCount % Number(params.meetingKeepEvery)===0){ startMeeting('定期同步:分工/进展/是否需要验证','general',null).catch(()=>{}) } }
308
+ function bumpArtifacts(){ artifactCount+=1; markProgress(); if(!meetingState && !verifyState && !pendingMeeting && Number(params.meetingKeepEvery)>0 && artifactCount % Number(params.meetingKeepEvery)===0){ startMeeting('定期同步:分工/进展/是否需要验证','general',null).catch(()=>{}) } }
309
309
  function listResidents(){ return Array.from(residents.values()).map(r=>({id:r.rId,direction:r.direction,status:r.status,rounds:r.rounds,contextPct:r.contextPct,insight:r.insight?r.insight.slice(0,80):''})) }
310
310
  // identify WHICH resident is calling a resident-facing tool: match the caller's
311
311
  // subagent id to a resident's childId. Fall back to the last-woken resident when
@@ -370,7 +370,11 @@ export function apply(ctx) {
370
370
  // A meeting must NOT preempt an active or pending verification (unanimous-consensus is the
371
371
  // group's truth-making step; preempting it would let every round resurface the same conflict).
372
372
  // Wait instead of stealing the floor: park the request and resume it after the verify settles.
373
- if(verifyState || pendingVerify){ pendingMeeting = { agenda, type:type||'general', targetId:targetId||null }; return {ok:true,deferred:true,during:'verify'} }
373
+ if(verifyState || pendingVerify){
374
+ // Keep the FIRST deferred request (never overwrite an earlier one with a later agenda).
375
+ if(!pendingMeeting) pendingMeeting = { agenda, type:type||'general', targetId:targetId||null }
376
+ return {ok:true,deferred:true,during:'verify'}
377
+ }
374
378
  clearHeartbeat()
375
379
  const ids=Array.from(residents.keys())
376
380
  // Rotate the per-meeting speaking order so the SAME resident isn't always the "first speaker
@@ -604,7 +608,10 @@ export function apply(ctx) {
604
608
  await saveAll()
605
609
  if(!ok) continue // a failed wake must NOT stop the fill; try the next idle resident
606
610
  }
607
- if(started>0) { return } // at least one started; their onResidentEnd re-drives scheduleNext
611
+ if(started>0) { armHeartbeat(); return } // started some; re-drive comes via onResidentEnd, BUT also arm a
612
+ // safety-net heartbeat so a woken resident whose subagent/end NEVER arrives (a hung normal round) does not
613
+ // freeze the group. Below mp, the next scheduleNext will re-fill; if all woken residents are stuck busy the
614
+ // heartbeat just re-arms harmlessly. (Meeting/verify already have recoverStallMs watchdogs; normal A-fill did not.)
608
615
  // everyone is busy or not idle-enough: arm a heartbeat to re-check later (no infinite spin)
609
616
  armHeartbeat()
610
617
  }
@@ -736,7 +743,14 @@ export function apply(ctx) {
736
743
  pendingVerify: pendingVerify?pendingVerify.targetId:null,
737
744
  meetings:meetings.length, recentActivity: activityLog.slice(-8) } }
738
745
  async function addMember(direction){ const r=newResident(direction||''); await spawnResident(r); return {ok:true,id:r.rId,direction:r.direction} }
739
- async function removeMember(id){ const r=residents.get(id); if(!r) return {ok:false}; if(r.childId){ try{ subagents.interrupt(r.childId,{kind:'ancestor',agent:rootAgent}) }catch(e){} } residents.delete(id); busy.delete(id); mailboxes.delete(id); await saveAll(); return {ok:true} }
746
+ async function removeMember(id){ const r=residents.get(id); if(!r) return {ok:false}; if(r.childId){ try{ subagents.interrupt(r.childId,{kind:'ancestor',agent:rootAgent}) }catch(e){} } residents.delete(id); busy.delete(id); mailboxes.delete(id); wakeKind.delete(id)
747
+ // Reconcile in-progress coordination so a removed member cannot hang consensus or crash a round:
748
+ // drop its meeting speech / verify verdict / deferred-meeting / pending-verify if it owned them, and
749
+ // prune it from the meeting's speaking order so the find() there never selects a ghost.
750
+ if(meetingState){ delete meetingState.inputs[id]; meetingState.order=(meetingState.order||[]).filter(x=>x!==id) }
751
+ if(verifyState){ delete verifyState.verdicts[id] }
752
+ if(pendingVerify && pendingVerify.proposer===id) pendingVerify=null
753
+ await saveAll(); return {ok:true} }
740
754
  // Normalize one parameter value to its intended type so a string from /v4 set or configure
741
755
  // becomes the right number/array. Keeps settings.json clean regardless of how it was set.
742
756
  function normalizeParam(k, v){
@@ -553,7 +553,8 @@ VibeMath/Projects/<project>/
553
553
  - 分级保活 B 增加 `busy.size===0` 守卫:任何常驻正在工作时不触发,避免预抢占在途轮次。
554
554
 
555
555
  ### 会议与验证互斥(不抢占)
556
- - 并行填充常驻后,一个常驻可能"提议验证(propose_verify)"而另一个同时"提议开会(propose_meeting)"。**会议不得抢占验证**:`startMeeting` 在 `verifyState || pendingVerify` 时改为把会议请求**暂存**(`pendingMeeting`,仅记录 agenda/type/target)并返回 `{deferred:true}`;`scheduleNext` 在所有 meeting/verify/pending 都清空后才恢复该暂存会议。这样统一共识验证(全真/全假)作为"求真"环节不会被会议的协调讨论打断,验证做完后再开会开会协调下一步——两者互斥但都不丢失(暂存会议之后补开)。
556
+ - 并行填充常驻后,一个常驻可能"提议验证(propose_verify)"而另一个同时"提议开会(propose_meeting)"。**会议不得抢占验证**:`startMeeting` 在 `verifyState || pendingVerify` 时改为把会议请求**暂存**(`pendingMeeting`,仅记录 agenda/type/target)并返回 `{deferred:true}`;`scheduleNext` 在所有 meeting/verify/pending 都清空后才恢复该暂存会议。这样统一共识验证(全真/全假)作为"求真"环节不会被会议的协调讨论打断,验证做完后再开会开会协调下一步——两者互斥但都不丢失(暂存会议之后补开)。**暂存只保留第一条**(`!pendingMeeting` 才写入),避免后到的请求覆盖先到的。
557
+ - **进行中增删常驻的一致性**:在会议/验证进行中 `removeMember` 会**同步清理**该常驻的会议发言(`delete meetingState.inputs[id]`)、验证投票(`delete verifyState.verdicts[id]`)、若它是待验证的提出者则清 `pendingVerify`,并从会议发言顺序 `st.order` 里剔除它;`wakeResident` 对已经不存在的常驻**防御性返回 false**(不再因 `r.childId` 抛 TypeError)。这样移除一个常驻不会让共识**卡在幽灵身上**,也不会让会议/验证循环去唤醒一个已删除的常驻而导致崩溃。
557
558
 
558
559
  > 效果:一个卡死/坏掉的会议或验证最多阻塞 `activityTimeoutMs`×2 后自动释放,团队重新回到 A/B 分级保活,**不会永久停死**。仍符合"框架只促成、从不指派任务"(放弃只是终止一个无法推进的会议,把控制权交还团队的自组织循环)。
559
560
  >