dsh-vibe-math 2.0.19 → 2.0.20
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.20",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
7
7
|
"node": "^22.19.0 || >=24.0.0"
|
|
@@ -338,8 +338,10 @@ export function apply(ctx) {
|
|
|
338
338
|
async function writeTaskboard(){ const lines=['# 任务板','']; for(const t of taskboard){ lines.push('- ['+t.status+'] '+t.title+(t.claimer?('(认领:'+t.claimer+')'):'')+(t.proposer?('(提议:'+t.proposer+')'):'')+(t.description?(':'+t.description):'')) } await writeText('Shared/taskboard.md',lines.join('\n')) }
|
|
339
339
|
async function proposeTask(title,description,proposer){ const id='t-'+shortId(); taskboard.push({id,title:String(title),description:String(description||''),status:'open',proposer:proposer||'',claimer:'',source:''}); await saveTaskboard(); markProgress(); logActivity('task','proposed '+id+'「'+title+'」'); return {ok:true,id} }
|
|
340
340
|
async function claimTask(id,claimer){ const t=taskboard.find(x=>x.id===id); if(!t) return {ok:false,message:'no such task'}; if(t.status!=='open') return {ok:false,message:'task already '+t.status}; t.status='claimed'; t.claimer=claimer; await saveTaskboard(); markProgress(); logActivity('task',claimer+' claimed '+id);
|
|
341
|
-
// wake the claimer to work on it (framework moves the task, resident decides how)
|
|
342
|
-
|
|
341
|
+
// wake the claimer to work on it (framework moves the task, resident decides how).
|
|
342
|
+
// NOT while paused/stopped: a paused run must not start new work — the claim is recorded on the
|
|
343
|
+
// board and the resident (who claimed it) picks it up again after resume.
|
|
344
|
+
const r=residents.get(claimer); if(r && !busy.has(claimer) && running && !autoDone){ currentResident=claimer; await wakeResident(r, (await normalPrompt(r))+'\n\n[YOU CLAIMED TASK '+id+'] '+t.title+' — '+t.description,'normal'); await saveAll() }
|
|
343
345
|
return {ok:true} }
|
|
344
346
|
async function taskDone(id,claimer){ const t=taskboard.find(x=>x.id===id); if(!t) return {ok:false}; t.status='done'; t.doneBy=claimer; await saveTaskboard(); await writeTaskboard(); markProgress(); logActivity('task','done '+id); return {ok:true} }
|
|
345
347
|
async function saveTaskboard(){ await writeJson('State/taskboard.json',taskboard); await writeTaskboard() }
|
|
@@ -348,7 +350,7 @@ export function apply(ctx) {
|
|
|
348
350
|
// Apply context/compact bookkeeping from a resident's reply, so the flag can clear even when
|
|
349
351
|
// the reply came through a meeting/verify branch (defensive) as well as the normal branch.
|
|
350
352
|
function postmark(r, parsed){
|
|
351
|
-
|
|
353
|
+
const cp=Number(parsed.contextPct); if(Number.isFinite(cp)) r.contextPct=clPct(cp) // tolerate numeric strings ("40")
|
|
352
354
|
if(parsed.compacted===true || (r.needCompact && parsed.summary)){
|
|
353
355
|
r.contextSeed=String(parsed.summary||r.contextSeed||'')
|
|
354
356
|
r.contextPct=Math.min(r.contextPct||15,25)
|
|
@@ -444,7 +446,10 @@ export function apply(ctx) {
|
|
|
444
446
|
const lines=['# 会议 '+st.id+'|'+fmtTime(),'','**议程**:'+st.agenda,'']
|
|
445
447
|
for(const [id,iv] of Object.entries(st.inputs)){ lines.push('### '+id); lines.push(iv.input||''); lines.push('') }
|
|
446
448
|
await writeText('Shared/meetings/'+st.id+'.md', lines.join('\n'))
|
|
447
|
-
meetings
|
|
449
|
+
// the full transcript lives on disk (Shared/meetings/<id>.md); the State array keeps a small
|
|
450
|
+
// index (id/agenda/at) so session.json does not carry a second copy of every transcript and
|
|
451
|
+
// rewrite it on EVERY saveAll during long runs (reports below are capped for the same reason).
|
|
452
|
+
meetings.push({id:st.id,agenda:st.agenda,at:now()}); if(meetings.length>200) meetings.shift()
|
|
448
453
|
logDecision('meeting',st.agenda)
|
|
449
454
|
// handle what the meeting produced: task proposals/claims, verify targets, stop vote
|
|
450
455
|
for(const [id,iv] of Object.entries(st.inputs)){
|
|
@@ -823,7 +828,7 @@ export function apply(ctx) {
|
|
|
823
828
|
}
|
|
824
829
|
// normal turn
|
|
825
830
|
if(r.status==='brainstorm'){ r.insight=parsed.summary||output; r.status='active' }
|
|
826
|
-
if(typeof parsed.solved==='boolean') reports.push({rId:r.rId,solved:parsed.solved,summary:parsed.summary||'',at:now()})
|
|
831
|
+
if(typeof parsed.solved==='boolean'){ reports.push({rId:r.rId,solved:parsed.solved,summary:parsed.summary||'',at:now()}); if(reports.length>100) reports.shift() } // solved-signal ring (not surfaced in status/report)
|
|
827
832
|
if(parsed.propose_verify) maybeQueueVerify(parsed.propose_verify, r.rId)
|
|
828
833
|
// group-conversation relay: the resident may choose to speak to the whole team (input) —
|
|
829
834
|
// forward it to the others so this is a real discussion group, not private monologues.
|
|
@@ -865,7 +870,15 @@ export function apply(ctx) {
|
|
|
865
870
|
await saveAll(); return {ok:true,message:'v4 started: '+params.residentCount+' resident(s) brainstorming',project:currentProject}
|
|
866
871
|
}
|
|
867
872
|
async function resume(){
|
|
868
|
-
currentProject=await readCurrentProject(); await ensureDirs()
|
|
873
|
+
currentProject=await readCurrentProject(); await ensureDirs()
|
|
874
|
+
// Resume is only meaningful for a stopped/paused/crashed run. If THIS process is already driving
|
|
875
|
+
// a live run whose disk state belongs to it, loadAll below would overwrite the in-memory state
|
|
876
|
+
// with a slightly stale snapshot (busy marks, wake round counters, mailbox contents from the last
|
|
877
|
+
// saveAll) — a silent clobber for a useless "kick". No-op instead. A cross-process restart is
|
|
878
|
+
// always allowed: its disk epoch differs, so the in-memory state is empty/stale anyway.
|
|
879
|
+
const pre=await readJson('State/session.json')
|
|
880
|
+
if(running && !autoDone && pre && pre.processEpoch===processEpoch) return {ok:true,message:'already running (no-op)'}
|
|
881
|
+
await loadAll(); await loadSettings()
|
|
869
882
|
// A run the group CONCLUDED (unanimous voteSolved → autoDone) must not be silently revived into
|
|
870
883
|
// a zombie that keeps waking residents with no consensus that it should still run. The group
|
|
871
884
|
// decided it is done; continuing means a NEW run (vibe_v4_start / vibe_v4_configure).
|
|
@@ -953,6 +966,11 @@ export function apply(ctx) {
|
|
|
953
966
|
// Create/configure a project and set params/problem WITHOUT starting any resident.
|
|
954
967
|
// The intended flow: vibe_v4_configure {project?, problem?, params?} → vibe_v4_start {}.
|
|
955
968
|
async function configure(cfg){
|
|
969
|
+
// configure is the PRE-START setup tool (project/problem/params). Switching the project while a
|
|
970
|
+
// run is LIVE would split the run's state across two trees: residents' briefs & libraries point
|
|
971
|
+
// at the OLD frameworkRoot while every subsequent saveAll/transcript/Verified card would go to the
|
|
972
|
+
// NEW project. Params tuning mid-run belongs to vibe_v4_set.
|
|
973
|
+
if(running && !autoDone) return {ok:false,message:'cannot configure while a run is running (pause or abort first; use vibe_v4_set to tune params)'}
|
|
956
974
|
if(cfg && cfg.project && String(cfg.project).trim()) currentProject=String(cfg.project).trim()
|
|
957
975
|
if(cfg && cfg.problem) problemText=String(cfg.problem)
|
|
958
976
|
if(cfg && cfg.params && typeof cfg.params==='object') setParams(cfg.params)
|
|
@@ -962,7 +980,13 @@ export function apply(ctx) {
|
|
|
962
980
|
await saveAll()
|
|
963
981
|
return {ok:true,project:currentProject,problem:problemText?problemText.slice(0,60):'',params:Object.keys(params).map(k=>k+'='+params[k]).join(', ')}
|
|
964
982
|
}
|
|
965
|
-
async function initAbort(){ clearHeartbeat(); running=false; phase='idle'; autoDone=false; for(const [,r] of residents){ if(r.childId){ try{ subagents.interrupt(r.childId,{kind:'ancestor',agent:rootAgent}) }catch(e){} } r.childId=''; r.lastActiveAt=0; r.roundsSinceCompact=0 }
|
|
983
|
+
async function initAbort(){ clearHeartbeat(); running=false; phase='idle'; autoDone=false; for(const [,r] of residents){ if(r.childId){ try{ subagents.interrupt(r.childId,{kind:'ancestor',agent:rootAgent}) }catch(e){} } r.childId=''; r.lastActiveAt=0; r.roundsSinceCompact=0 }
|
|
984
|
+
// Wipe the coordination state too: an aborted run must not report an in-flight meeting/verify,
|
|
985
|
+
// a parked meeting, a verify queue, or busy residents (their childIds are gone, so no end event
|
|
986
|
+
// can ever clear those marks). resume()/start() re-initialize anyway; this keeps status truthful
|
|
987
|
+
// between abort and the next action.
|
|
988
|
+
meetingState=null; verifyState=null; pendingMeeting=null; pendingVerify=[]; busy=new Set(); wakeKind=new Map(); currentResident=''; finalizeLock=null
|
|
989
|
+
await saveAll(); return {ok:true,message:'aborted'} }
|
|
966
990
|
function setPause(){ clearHeartbeat(); running=false; return {ok:true,message:'paused'} }
|
|
967
991
|
|
|
968
992
|
return {
|
|
@@ -570,7 +570,22 @@ 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` 107/107(T1–T37,后续审计回归见 §27/§28/§29)、v3 100/100、v2 business 18/regression 14、multisession 25/25。
|
|
574
|
+
|
|
575
|
+
## 29. 第五轮全面深度审计(npm v2.0.20,遗留区域 + 未修改逻辑)
|
|
576
|
+
|
|
577
|
+
对历轮尚未触达的"牵连对象/未改逻辑"做复查,发现并修复 5 处(新增回归 T33–T37):
|
|
578
|
+
|
|
579
|
+
- **运行中 resume 用陈旧磁盘快照覆盖内存态(静默 clobber)**:resume 先 `loadAll` 再用磁盘状态覆盖内存——若某进程已在本进程内驱动着活 run(有人把 resume 当"踢一脚"用),内存里比磁盘新一个事件的 busy/轮次/邮箱状态会被回退到最近一次 saveAll 的快照。修复:resume 开头预读 `session.json`,若内存 `running && !autoDone` **且磁盘 epoch 属于本进程**(同进程活 run),直接返回 `{ok:true,message:'already running (no-op)'}`——不做任何加载;跨进程重启(epoch 不同)不受影响(A4 场景依旧放行)。**T33**。
|
|
580
|
+
- **configure 在运行中切换项目 → 状态分裂到两棵树**:configure 是"启动前"工具,但运行中调用会把 currentProject 改到新项目:常驻的简报/资料库仍在旧树,而之后的 saveAll/会议纪要/Verified 卡全写到新树。修复:`running && !autoDone` 时拒绝并提示改用 `vibe_v4_set` 调参数。**T34**。
|
|
581
|
+
- **abort 后 status 谎报在途协调态**:initAbort 只停调度并清 childId,会议/验证/暂存会议/验证队列/busy 全部残留——被中断常驻的 end 因 childId 已清无法命中,busy 印记永远无人清除,status 显示"会议进行中/验证中/busy=[r-1]",而 run 早已 running=false。修复:initAbort 一并清空 `meetingState/verifyState/pendingMeeting/pendingVerify/busy/wakeKind/currentResident/finalizeLock`。**T35**。
|
|
582
|
+
- **暂停期间 claim 任务会僵尸唤醒认领者**:v2.0.18 的暂停门控只覆盖了 end 处理器;`claimTask` 的直接唤醒绕过了它——暂停时某个 end 回复里 `claim_task`(或宿主工具认领)会把认领者拉起来做一轮新工作。修复:认领记录照常入板,但唤醒加 `running && !autoDone` 门控(认领者自己知道认领了什么,恢复后自然接续)。**T36**。
|
|
583
|
+
- **reports/meetings 无界膨胀(session.json 每事件全量重写)**:`reports` 只写不读,且每个普通轮 end(模板自带 `solved:false`)都 push 一条;`meetings` 数组把**完整会议全文**再存一份(磁盘 `Shared/meetings/<id>.md` 已有),长 run 中 session.json 越来越大、每次 saveAll 都重写整份。修复:reports 上限 100(环形),meetings 只存 {id,agenda,at} 小索引(上限 200)——全文仍在磁盘,会议计数/报告不受影响。**T37**。
|
|
584
|
+
- **连带小修**:`postmark` 的 contextPct 只认 number,模型报数字字符串("40")时不生效;现兼容数字字符串。
|
|
585
|
+
|
|
586
|
+
> 边界复查(未改,记录):暂停中 `postMessage`(显式宿主动作)仍会投递唤醒(与"认领"不同,是人的明确指令);brainstorm 期首轮 end 永不触发、以及"邮箱在超长共识链后送达"维持 §27/§28 的设计边界。
|
|
587
|
+
>
|
|
588
|
+
> 全套测试仍全绿:`selfdrive-v4` 21/21、`e2e-v4-fixes` 107/107(T1–T37)、v3 100/100、v2 business 18/regression 14、multisession 25/25、selfdrive-v3 0 异常。
|
|
574
589
|
|
|
575
590
|
## 27. 第三轮全面深度审计(npm v2.0.18,牵连对象/逻辑)
|
|
576
591
|
|