dsh-vibe-math 2.0.18 → 2.0.19
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.
|
|
4
|
+
"version": "2.0.19",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -233,7 +233,7 @@ export function apply(ctx) {
|
|
|
233
233
|
+'\n团队成员:\n'+banner()+'\n'
|
|
234
234
|
+'New items:\n'+ (await inboxText(r.rId)) +'\n'
|
|
235
235
|
+'Reply with ONLY a JSON object:\n'
|
|
236
|
-
+'{"summary":"<what you did / decided this round, 1-3 sentences>","input":"<optional: a message to the whole team, or \\"\\">","solved":false,"propose_verify":"<id|null>","propose_meeting":"<agenda|null>","propose_task":"<task title|null>","claim_task":"<task id|null>","task_done":"<task id|null>","contextPct":40}'
|
|
236
|
+
+'{"summary":"<what you did / decided this round, 1-3 sentences>","input":"<optional: a message to the whole team, or \\"\\">","solved":false,"propose_verify":"<id|null>","propose_meeting":"<agenda|null>","propose_task":"<task title|null>","task_desc":"<optional: why this task matters / what it covers|null>","claim_task":"<task id|null>","task_done":"<task id|null>","contextPct":40}'
|
|
237
237
|
}
|
|
238
238
|
function meetingPrompt(r, st){
|
|
239
239
|
const prior=Object.entries(st.inputs).filter(([k])=>k!==r.rId).map(([k,iv])=>' ['+k+'] '+String(iv.input||iv.summary||'')).join('\n')
|
|
@@ -321,10 +321,10 @@ export function apply(ctx) {
|
|
|
321
321
|
function byChild(childId){ for(const [,r] of residents){ if(r.childId===childId) return r } return undefined }
|
|
322
322
|
|
|
323
323
|
// ---- artifact writers (resident-facing) ----
|
|
324
|
-
async function publishProgress(rId,content){ const rel='Progress/'+rId+'/progress.md'; const prev=(await readText(rel))||''; await writeText(rel, prev+'\n### '+fmtTime()+'|'+rId+'\n'+String(content||'')+'\n'); return {ok:true} }
|
|
325
|
-
async function recordProposition(rId,o){ const id=o.id||('p-'+shortId()); const lines=['# 命题|'+(o.title||id),'- 标题: '+(o.title||id),'- ID: '+id,'- 类型: 命题','- 状态: 未定论','- 概率: '+cl(o.prob!=null?o.prob:0.5),'- 价值程度: '+cl(o.value!=null?o.value:0.5),'- 动机用途计划: '+(o.motivation||''),'- 依赖: []','','## 陈述',String(o.statement||''),'','## 证明尝试','','## 证伪尝试','']; await writeText('Propos/'+rId+'/'+id+'.md',lines.join('\n')); logActivity('record',rId+' 命题 '+id); bumpArtifacts(); return {ok:true,id,file:'Propos/'+rId+'/'+id+'.md'} }
|
|
326
|
-
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'} }
|
|
327
|
-
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'} }
|
|
324
|
+
async function publishProgress(rId,content){ if(!rId||!residents.has(rId)) return {ok:false,message:'no such resident'} ; const rel='Progress/'+rId+'/progress.md'; const prev=(await readText(rel))||''; await writeText(rel, prev+'\n### '+fmtTime()+'|'+rId+'\n'+String(content||'')+'\n'); return {ok:true} }
|
|
325
|
+
async function recordProposition(rId,o){ if(!rId||!residents.has(rId)) return {ok:false,message:'no such resident'} ; const id=o.id||('p-'+shortId()); const lines=['# 命题|'+(o.title||id),'- 标题: '+(o.title||id),'- ID: '+id,'- 类型: 命题','- 状态: 未定论','- 概率: '+cl(o.prob!=null?o.prob:0.5),'- 价值程度: '+cl(o.value!=null?o.value:0.5),'- 动机用途计划: '+(o.motivation||''),'- 依赖: []','','## 陈述',String(o.statement||''),'','## 证明尝试','','## 证伪尝试','']; await writeText('Propos/'+rId+'/'+id+'.md',lines.join('\n')); logActivity('record',rId+' 命题 '+id); bumpArtifacts(); return {ok:true,id,file:'Propos/'+rId+'/'+id+'.md'} }
|
|
326
|
+
async function recordMethod(rId,o){ if(!rId||!residents.has(rId)) return {ok:false,message:'no such resident'} ; 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'} }
|
|
327
|
+
async function recordSubproblem(rId,o){ if(!rId||!residents.has(rId)) return {ok:false,message:'no such resident'} ; 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'} }
|
|
328
328
|
// auto-sync meeting: every meetingKeepEvery new artifacts, convene a general coordination meeting
|
|
329
329
|
function bumpArtifacts(){ artifactCount+=1; markProgress(); if(!meetingState && !verifyState && !pendingMeeting && Number(params.meetingKeepEvery)>0 && artifactCount % Number(params.meetingKeepEvery)===0){ startMeeting('定期同步:分工/进展/是否需要验证','general',null).catch(()=>{}) } }
|
|
330
330
|
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):''})) }
|
|
@@ -653,7 +653,7 @@ export function apply(ctx) {
|
|
|
653
653
|
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
654
654
|
+'Resident researcher '+r.rId+' — CHECKPOINT(团队空闲,请由你们继续自主推进)。当前项目尚未解决(除非你已确认)。团队在等待有人继续:请**继续解决这个问题**——读他人的库对齐、推进某个子问题/引理/方法、尝试一条路线;或向团队发消息(input)、提议任务(propose_task)让大家分工。若你确实认为问题已解决、或已彻底无路可走,才提议开会(propose_meeting)让团队表决/商量、或声明 solved=true。默认立场是:**请推进,而不是停在原地。**\n'
|
|
655
655
|
+'Reply with ONLY a JSON object:\n'
|
|
656
|
-
+'{"summary":"<what you will do / what you advanced this round>","input":"<optional: a message to the whole team, or \\"\\">","solved":false,"propose_verify":"<id|null>","propose_meeting":"<agenda|null>","propose_task":"<task title|null>","claim_task":"<id|null>","contextPct":40}'
|
|
656
|
+
+'{"summary":"<what you will do / what you advanced this round>","input":"<optional: a message to the whole team, or \\"\\">","solved":false,"propose_verify":"<id|null>","propose_meeting":"<agenda|null>","propose_task":"<task title|null>","task_desc":"<optional: why this task matters / what it covers|null>","claim_task":"<id|null>","contextPct":40}'
|
|
657
657
|
}
|
|
658
658
|
function clearHeartbeat(){ if(heartbeatDisposer!==null){ try{ heartbeatDisposer() }catch(e){} heartbeatDisposer=null } }
|
|
659
659
|
function armHeartbeat(){
|
|
@@ -774,7 +774,13 @@ export function apply(ctx) {
|
|
|
774
774
|
// ---- resident end handler ----
|
|
775
775
|
async function onResidentEnd(childId, info){
|
|
776
776
|
const r=byChild(childId); if(!r) return
|
|
777
|
-
busy
|
|
777
|
+
// A turn that is NOT marked busy is a duplicate/stale end (the same subagent/end delivered twice,
|
|
778
|
+
// or an end for a turn already settled). Without this guard every side effect below — task
|
|
779
|
+
// proposal, group relay, verify queueing, meetings.push — would run a SECOND time (the
|
|
780
|
+
// duplicate-task/duplicate-stop class from test9 reappears whenever a host re-delivers an end).
|
|
781
|
+
// Every legitimate end corresponds to a busy turn: busy is added at spawn/wake and cleared only
|
|
782
|
+
// here, on wake failure, on removeMember, or on respawn (whose stale childIds no longer match).
|
|
783
|
+
if(!busy.delete(r.rId)) return
|
|
778
784
|
// Any resident turn that COMPLETED is real activity for the stall clock (B). Residents frequently
|
|
779
785
|
// write their libraries via direct fs (not the record* tools), so relying only on
|
|
780
786
|
// bumpArtifacts/markProgress would leave lastProgressAt stale and B would fire against an active
|
|
@@ -897,12 +903,14 @@ export function apply(ctx) {
|
|
|
897
903
|
function status(){ return { ok:true, running, phase, autoDone, project:currentProject, residentCount:residents.size,
|
|
898
904
|
residents:listResidents(), busy:[...busy], taskboard:taskboard.length,
|
|
899
905
|
meetingInProgress: !!(meetingState), verifyInProgress: !!(verifyState), pendingVerify: pendingVerify.length?pendingVerify[0].targetId:null, pendingVerifyCount: pendingVerify.length,
|
|
906
|
+
parkedMeeting: pendingMeeting?pendingMeeting.agenda:null,
|
|
900
907
|
params:['residentCount','compactAfterRounds','compactThreshold','maxParallel','activityTimeoutMs','meetingKeepEvery','verdictMaxRounds','stallAutoMeetingMs','provider','model','residentPersona','toolAllow','toolDeny'].map(k=>k+'='+(Array.isArray(params[k])?params[k].join(','):params[k])).join(', ') } }
|
|
901
908
|
function report(){ return { ok:true, running, phase, autoDone, project:currentProject, problem:problemText,
|
|
902
909
|
residents:listResidents(), taskboard:taskboard.filter(t=>t.status!=='done'),
|
|
903
910
|
meeting: meetingState?{id:meetingState.id, agenda:meetingState.agenda, spoke:Object.keys(meetingState.inputs).length+'/'+residents.size}:null,
|
|
904
911
|
verify: verifyState?{target:verifyState.targetId,stage:verifyState.stage, voted:Object.keys(verifyState.verdicts).length+'/'+residents.size}:null,
|
|
905
912
|
pendingVerify: pendingVerify.length?pendingVerify[0].targetId:null,
|
|
913
|
+
parkedMeeting: pendingMeeting?pendingMeeting.agenda:null,
|
|
906
914
|
meetings:meetings.length, recentActivity: activityLog.slice(-8) } }
|
|
907
915
|
async function addMember(direction){ const r=newResident(direction||''); await spawnResident(r)
|
|
908
916
|
// Mid-meeting additions must join the meeting's speaking order; otherwise allSpoke (over CURRENT
|
|
@@ -914,11 +922,14 @@ export function apply(ctx) {
|
|
|
914
922
|
return {ok:true,id:r.rId,direction:r.direction} }
|
|
915
923
|
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); if(currentResident===id) currentResident=''
|
|
916
924
|
// Reconcile in-progress coordination so a removed member cannot hang consensus or crash a round:
|
|
917
|
-
// drop its meeting speech / verify verdict
|
|
918
|
-
//
|
|
925
|
+
// drop its meeting speech / verify verdict and prune it from the meeting's speaking order so the
|
|
926
|
+
// find() there never selects a ghost. Its QUEUED verify proposals are deliberately KEPT: a
|
|
927
|
+
// proposal is a statement about an OBJECT the group can judge on its merits with its CURRENT
|
|
928
|
+
// members (allVoted recomputes over the live residents), and dropping the queue entry would also
|
|
929
|
+
// erase the intent of any OTHER member who independently proposed the same target (dedup keeps
|
|
930
|
+
// only the first entry, which may belong to the removed member).
|
|
919
931
|
if(meetingState){ delete meetingState.inputs[id]; meetingState.order=(meetingState.order||[]).filter(x=>x!==id) }
|
|
920
932
|
if(verifyState){ delete verifyState.verdicts[id] }
|
|
921
|
-
if(pendingVerify.length) pendingVerify = pendingVerify.filter(p=>p.proposer!==id)
|
|
922
933
|
await saveAll()
|
|
923
934
|
// Re-drive the scheduler right away. If the removed member was the ONLY turn in flight (e.g. the
|
|
924
935
|
// last unspoken meeting speaker / the last unvoted voter, interrupted mid-turn), NO subagent/end
|
|
@@ -959,7 +970,7 @@ export function apply(ctx) {
|
|
|
959
970
|
onResidentEnd, start, resume, status, report, addMember, removeMember, setParams,
|
|
960
971
|
setPause, initAbort, postMessage, startMeeting, saveAll, broadcast, configure, loadSettings,
|
|
961
972
|
currentResident:()=>currentResident,
|
|
962
|
-
residentIdOf:(agent)=>{ const m=residentOfAgent(agent); return m
|
|
973
|
+
residentIdOf:(agent)=>{ const m=residentOfAgent(agent); if(m) return m; const c=currentResident; return (c && residents.has(c)) ? c : '' },
|
|
963
974
|
useResident:(id)=>{ currentResident=id },
|
|
964
975
|
publishProgress, recordProposition, recordMethod, recordSubproblem, listResidents, reportContext,
|
|
965
976
|
proposeTask, claimTask, taskDone, listTasks,
|
|
@@ -570,7 +570,7 @@ VibeMath/Projects/<project>/
|
|
|
570
570
|
>
|
|
571
571
|
> 说明:无法对"某常驻真的拒绝/掉线"的情况达成全体一致时,看门狗会把该对象保留为"未定论/带概率",这是哲学上期望的诚实结果。`session.json` 仍不持久化 `meetingState`(进行中的会议不跨进程恢复),B 的停滞看门狗在重启后仍会触发,因此重启也能自愈。
|
|
572
572
|
>
|
|
573
|
-
> 全套测试仍全绿:`selfdrive-v4` 21/21、`e2e-v4-fixes`
|
|
573
|
+
> 全套测试仍全绿:`selfdrive-v4` 21/21、`e2e-v4-fixes` 94/94(T1–T32,后续审计回归见 §27/§28)、v3 100/100、v2 business 18/regression 14、multisession 25/25。
|
|
574
574
|
|
|
575
575
|
## 27. 第三轮全面深度审计(npm v2.0.18,牵连对象/逻辑)
|
|
576
576
|
|
|
@@ -587,6 +587,19 @@ VibeMath/Projects/<project>/
|
|
|
587
587
|
|
|
588
588
|
> 设计边界复查确认(未改):① 会议/验证轮次唤醒**不额外受 maxParallel 限制**——共识需要全员发言/投票;每个调度 pass 只唤醒一个未发言/未投票者,由各 end 事件串行驱动(残留的普通轮可能造成短暂并发,但不会无限累积);② 非一致(平均概率留库)的对象可被后续提议**再次端到端验证**(去重窗口只挡"刚定论为真/假"的对象)——重复提议者是在不知情时提议的,重验一轮不算错;③ 验证中途 `addMember` 的新成员会被要求投票(v2.0.17 注释行为,保持);④ 已定论 run 的成果随时可在磁盘读取,resume 拒绝只针对"自动复活"。
|
|
589
589
|
|
|
590
|
+
## 28. 第四轮全面深度审计(npm v2.0.19,对 v2.0.18 修复的牵连检查)
|
|
591
|
+
|
|
592
|
+
对 v2.0.18 的修复(FIFO 验证队列、会议暂存、暂停门控、writeJson 串行化等)做连带对象复查,发现并修复 4 处(新增回归 T29–T32):
|
|
593
|
+
|
|
594
|
+
- **同回合重复 `subagent/end` 会把每个副作用跑两遍**:`onResidentEnd` 对"已结算回合的重复/迟到 end"无守卫——重复投递同一 end(宿主重放、桥接层抖动)会让 propose_task / 群聊转发 / 验证入队 / meetings.push **全部二次执行**(test9 的重复任务/重复 stop 一类问题在"重复 end"场景会原样复发)。修复:回合必须以 busy 标记在册为前提——`if(!busy.delete(r.rId)) return`(每次合法 end 都对应一次 spawn/wake 置位的 busy;busy 仅在本处、唤醒失败、removeMember、重生成时清除,而后者 stale childId 已无法 byChild 命中)。**T29**:同一 tick 内连发两次相同 end → 任务只提议一次、群聊只转发一次。
|
|
595
|
+
- **空/失效 rId 的 resident 写入工具会制造库根散卡**:`currentResident` 被复位为 `''`(如移除最后一名常驻后)时,主机/未知代理调用 `vibe_v4_record_*`/`vibe_v4_publish_progress` 会把路径 `Propos//p-x.md` 塌缩成**库根目录的散乱卡片**(正是 test9 曾出现的 0 字节散卡一类问题)。修复:`residentIdOf` 回退仅当 `currentResident` 仍真实存在时生效,否则返回 `''`;四个库写入函数对空/未知 rId 直接拒绝 `{ok:false}`(主机以 `currentResident` 代写这一既有便利不受影响——自驱动测试仍走该回退)。**T30**。
|
|
596
|
+
- **移除者的已排队验证提议被丢弃 → 提议静默蒸发(含"第二提议者意图被去重吞掉"边角)**:v2.0.12 遗留的"移除提议者则清掉其 pendingVerify"在 FIFO 队列下会把该成员的排队提议**整条删除**;且同目标被两人提议时去重只保留第一人的条目——若第一人被移除,第二人的意图同样蒸发。修复:`removeMember` **不再过滤验证队列**——提议是关于对象的陈述,由**当前成员**按对象价值共识判定(allVoted 本就按实时成员集计算,写回扫描也不依赖提出者存续)。**T31**:r-3 提议 p-x 后在 p-y 验证中被移除 → p-x 仍由剩余成员完整验证到 Verified/。
|
|
597
|
+
- **暂存的会议对用户不可见 / 普通轮提议任务永远没有描述**:`status/report` 新增 `parkedMeeting`(暂存会议议程),便于确认"会议没丢、在排队"(**T32** 同时钉住"brainstorm 期开会 → 暂存 → bootstrap 后真正召开",不再被看门狗误杀);普通轮/心跳提示词模板补上 `task_desc` 字段(此前普通轮提议任务时描述恒为空,只有会议轮能带描述)。
|
|
598
|
+
|
|
599
|
+
> 边界复查(未改,记录):brainstorm 阶段若某常驻首轮 end 永不触发,run 停在 brainstorm(brainstorm 无看门狗、无心跳可唤醒"已空闲"者推进)——真实 DSH 的轮次必然以 completed/error/timeout 结束并触发 end,纯属框架外故障,不做可能"静默丢掉慢成员声音"的自动跳过;`Shared/taskboard.md`(人类视图)由调用时快照生成、非逐文件串行,最坏情况短暂滞后于 `State/taskboard.json`(权威源),下次任务动作即自愈。
|
|
600
|
+
>
|
|
601
|
+
> 全套测试仍全绿:`selfdrive-v4` 21/21、`e2e-v4-fixes` 94/94(T1–T32)、v3 100/100、v2 business 18/regression 14、multisession 25/25、selfdrive-v3 0 异常。
|
|
602
|
+
|
|
590
603
|
|
|
591
604
|
|
|
592
605
|
|