dsh-vibe-math 1.3.8 → 1.4.0

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
@@ -61,6 +61,10 @@
61
61
  > 🔧 **v1.3.7 哲学回归(清晰提示词 + 真实交流群 + 直接写文件)**:常驻首轮注入完整 `contextBrief`(背景/使命、工作模式、文件与格式、工具、规则);会议把其他常驻实际发言(input)转给每个人看,常驻日常轮的 `input` 经 `relayToGroup` 转发到其它常驻邮箱(像群聊);常驻**直接用 fs 写自己的 md**;去固定约束改为团队讨论涌现。详见 §20。
62
62
  >
63
63
  > 🔧 **v1.3.8 基于真实测试的诊断修复**:**① 共识验证真正"全体一致"**——`finalizeVerify` 现在要求**全体在册常驻都投了票**才可判"一致",否则辩论或保留为未定论(实测曾出现 2/4 投票却被判"全体一致为真",已修);**② 会议必须全体发言**——`continueMeetingRound` 按"是否已发言"收口,`allSolved`(stop)要求全员发言+全票 true,杜绝缺席成员被带偏;**③ 背景只在首轮讲一次**——`contextBrief` 只在 `brainstormPrompt`(首轮)注入完整版,后续 normal/meeting/verify/CHECKPOINT 用极简当前状态,不再每轮重复长背景(省上下文);**④ 验证目标按提出者精确定位**(`targetOwner` + `findSourceRel` 优先提出者库,避免同名 id 撞车);**⑤ 主代理放权**——persona 明确"让常驻自组织(hands-off)",不注议程/优先级/分工/验证决定,只 read status/report,用户明确要求或明显僵死时才 message/meeting 且只促成不决定。详见 §21。
64
+ >
65
+ > 🔧 **v1.3.9 进一步按哲学打磨**:**① 会议议程来源**确认是非 bug(r-1 的 `propose_meeting` 发起);**② 压缩后重申核心规则**——每次压缩触发时在提示开头重申短核心规则(治"压缩遗忘规则"),其余轮仍极简;**③ 验证 `verdict` 明确为 0–1 正确概率**——1=绝对为真/判真、0=绝对为假/判假、0.5=不确定,"全体一致判真(verdict=1)/判假(verdict=0)才算数",未全票留库附平均正确概率(兼容旧字符串);**④ 创建项目不立即启动**——新增 `vibe_v4_configure {project?, problem?, params?}` 只建/配项目与参数(持久化 `State/settings.json`)不唤醒常驻,随后 `vibe_v4_start` 才启动;支持设置**项目名**。详见 §22。
66
+ >
67
+ > 🔧 **v1.4.0 verdict 改为纯概率数值 + 全面审计修复**:**① `verdict` 是纯 0–1 正确概率(程度),不再二分类**——仅当**全体一致给 1(真)或全体一致给 0(假)**才按真/假写入 Verified/,否则只作为概率数值保留、附全组平均正确概率(0.97 不再算"真",属更严格的绝对一致口径);**② 审计修复**:`resume` 补 `loadSettings()`(跨进程不再重置参数)、`configure` 直接写出问题卡、补上缺失的 `/v4 set` 分支、真实 `/compact` 成功后置 `needCompact` 以**重申核心规则**。详见 §23。
64
68
 
65
69
  ---
66
70
 
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 — FOUR agent presets in one install: vibe-math-v1 (classic pipeline), 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 four presets into the DSH preset root.",
4
- "version": "1.3.8",
4
+ "version": "1.4.0",
5
5
  "type": "module",
6
6
  "main": "installer.js",
7
7
  "exports": {
@@ -51,16 +51,16 @@
51
51
  task board / debates), Verified/ (read-only, ONLY after unanimous consensus),
52
52
  State/ (framework-private), Reliable/ (references), Notes/.
53
53
 
54
- Main controls:
55
- - vibe_v4_start {problem, residentCount?, seedDirections?} — spawn residents, brainstorm, begin.
56
- - vibe_v4_resumeresume a persisted run.
57
- - vibe_v4_pause / vibe_v4_abort / vibe_v4_status / vibe_v4_report.
54
+ Main controls (recommended flow: configure FIRST, then start):
55
+ - vibe_v4_configure {project?, problem?, params?} — create/configure the project (name, problem, params) WITHOUT starting a run; set everything here first.
56
+ - vibe_v4_start {problem?, residentCount?, seedDirections?} begin the run (spawn residents, brainstorm). If problem was configured, omit it.
57
+ - vibe_v4_set {residentCount, compactThreshold, compactAfterRounds, meetingKeepEvery, maxParallel, activityTimeoutMs, verdictMaxRounds} — tune params (persisted to the settings file).
58
+ - vibe_v4_resume / vibe_v4_pause / vibe_v4_abort / vibe_v4_status / vibe_v4_report.
58
59
  - vibe_v4_message {to|all, content} — inject a message to a resident (human/assistant intervention).
59
60
  - vibe_v4_meeting {agenda} — force a meeting.
60
61
  - vibe_v4_add_member {direction?} / vibe_v4_remove_member {id} — add / close a resident.
61
62
  - vibe_v4_list_members — list residents.
62
- - vibe_v4_set {compactAfterRounds, compactThreshold, residentCount, maxParallel, activityTimeoutMs}.
63
- A /v4 slash command mirrors the main controls.
63
+ A /v4 slash command mirrors the main controls (configure|start|resume|pause|abort|status|report|meeting|members|add|remove|set).
64
64
 
65
65
  TRUST RULE: only Verified/ (and Propos/ entries marked 已验证·真/假) are absolutely
66
66
  trustworthy; everything else — unverified resident claims, Progress/, Method claims —
@@ -157,6 +157,13 @@ export function apply(ctx) {
157
157
  s.push('- 退出时**只**输出一个 JSON 对象(放在 ```json 代码围栏内;围栏外不要有文字)。')
158
158
  return s.join('\n')
159
159
  }
160
+ // A SHORT core-rules recap, re-injected ONLY right after a compaction so the resident
161
+ // never loses the ground rules (they are told fully once at brainstorm, but a /compact
162
+ // could blank them).
163
+ function coreRulesBrief(){
164
+ const base=frameworkRoot()
165
+ return '[核心规则重申] 只有 Verified/(及标记"已验证·真/假")算已确立;验证须全组一致(全真或全假)才作数,否则留库附平均概率;你只写自己的库('+base+'/ 的 Progress/<你>/、Propos/<你>/、Methods/<你>/、Subproblems/<你>/),可只读任何人的库;任务分工由团队讨论决定;退出只输出一个 JSON 对象。'
166
+ }
160
167
  function brainstormPrompt(r){
161
168
  return (params.residentPersona?params.residentPersona+'\n':'')
162
169
  +contextBrief(r,'full')+'\n'
@@ -187,14 +194,16 @@ export function apply(ctx) {
187
194
  +'{"input":"<your real contribution to this discussion>","propose_task":"<task title or null>","task_desc":"...","claim_task":"<task id or null>","propose_verify":"<id or null>","voteSolved":true}'
188
195
  }
189
196
  function verifyPrompt(r, vs){
190
- const others=Object.entries(vs.verdicts).map(([k,v])=>'- '+k+': '+v.verdict+' ('+v.confidence+') '+v.reason).join('\n')
197
+ const others=Object.entries(vs.verdicts).map(([k,v])=>'- '+k+': 正确概率 '+String(v.prob!=null?Number(v.prob).toFixed(2):0.5)+' '+v.reason).join('\n')
191
198
  return (params.residentPersona?params.residentPersona+'\n':'')
192
199
  +'Resident '+r.rId+' — 团队验证。 The group is verifying object '+vs.targetId+'('+vs.targetType+',提出者 '+vs.targetOwner+')。\n'
193
- +'只有**全体常驻一致判真(或一致判假)**才算数。请给出你**诚实独立的判断**'
200
+ +'请给出你对「该对象为真」的**正确概率 `verdict`**,仅一个 0–1 数值:**1 = 绝对为真,0 = 绝对为假,0.5 = 完全不确定,其余为介于其间的程度**(不要给 TRUE/FALSE,就给一个数值)。\n'
201
+ +'判定规则:仅当**全体常驻一致给 1(都认为是真)或一致给 0(都认为是假)**,才按「真/假」写入 Verified/;否则**只作为概率数值(一种程度)保留在库中**,附全组平均正确概率,不写成真/假。\n'
202
+ +'请给出你**诚实独立的判断**'
194
203
  +(vs.stage==='debate'?',并参考他人意见:\n':'。\n')
195
204
  +(vs.stage==='debate'&&others?('### 他人意见(已转发给你)\n'+others+'\n'):'')
196
205
  +'\nReply with ONLY a JSON object:\n'
197
- +'{"vote":{"verdict":"TRUE","confidence":0.8,"reason":"<your logic>"}}'
206
+ +'{"vote":{"verdict":0.9,"reason":"<your logic>"}}'
198
207
  }
199
208
 
200
209
  // ---- resident lifecycle ----
@@ -216,7 +225,8 @@ export function apply(ctx) {
216
225
  // framework uses as the next context seed (equivalent to /compact's "consolidate & forget").
217
226
  let prompt = promptText
218
227
  if(r.needCompact || (Number(r.contextPct)>=Number(params.compactThreshold)) || (r.roundsSinceCompact>=Number(params.compactAfterRounds))){
219
- prompt = '[CONTEXT COMPACT — your conversation is at/near the limit. Do NOT re-derive history.\n' +
228
+ prompt = coreRulesBrief() + '\n' +
229
+ '[CONTEXT COMPACT — your conversation is at/near the limit. Do NOT re-derive history.\n' +
220
230
  'Condense your current working state into ONE tight self-summary (findings so far, active direction, key artifacts you recorded, next concrete steps, open questions), then answer this round in the normal JSON format as usual.\n' +
221
231
  'Set "contextPct": 15 (your post-compact usage) and "compacted": true in the reply so the framework records the condensed seed.]\n\n' + promptText
222
232
  r.needCompact = true
@@ -311,7 +321,7 @@ export function apply(ctx) {
311
321
  }
312
322
  const votes=Object.values(st.inputs).map(x=>x.voteSolved).filter(v=>typeof v==='boolean')
313
323
  const allSolved = allSpoke && votes.length>0 && votes.every(v=>v===true)
314
- logActivity('meeting', 'concluded'+(allSolved?' → ALL agree solved':' (not all spoke / not unanimous)'))
324
+ logActivity('meeting', 'concluded'+(allSolved?' → ALL agree solved':' (no unanimous solved vote)'))
315
325
  if(allSolved){ running=false; autoDone=true; phase='done'; logActivity('stop','all residents agree: problem solved'); await saveAll(); return }
316
326
  meetingState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
317
327
  }
@@ -335,11 +345,12 @@ export function apply(ctx) {
335
345
  const vs=verifyState; const expected=Array.from(residents.keys()).length
336
346
  const allVoted = expected>0 && Object.keys(vs.verdicts).length>=expected
337
347
  const vals=Object.values(vs.verdicts)
338
- const allTrue = allVoted && vals.every(x=>x.verdict==='TRUE')
339
- const allFalse = allVoted && vals.every(x=>x.verdict==='FALSE')
348
+ // verdict is a PURE 0-1 probability; only ALL=1 (true) or ALL=0 (false) is a binary verdict.
349
+ const allTrue = allVoted && vals.every(x=>Number(x.prob)===1)
350
+ const allFalse = allVoted && vals.every(x=>Number(x.prob)===0)
340
351
  if(allTrue||allFalse){ await closeVerify(vs,allTrue); return }
341
352
  if(vs.round+1<params.verdictMaxRounds){ vs.stage='debate'; vs.round+=1; vs.asked=[]; logActivity('verify',vs.targetId+' round '+vs.round+' → debate'); await saveAll(); await scheduleNext(); return }
342
- const avg=vals.length? vals.reduce((a,x)=>a+(x.verdict==='TRUE'?x.confidence:x.verdict==='FALSE'?1-x.confidence:0.5),0)/vals.length : 0.5
353
+ const avg=vals.length? vals.reduce((a,x)=>a+(x.prob!=null?x.prob:0.5),0)/vals.length : 0.5
343
354
  await writeDebateDoc(vs,false,avg); await rewriteSourceProb(vs.targetId, avg, vs.targetOwner); logActivity('verify',vs.targetId+' NOT unanimous → kept unverified (avg '+avg.toFixed(2)+')')
344
355
  verifyState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
345
356
  }
@@ -353,7 +364,7 @@ export function apply(ctx) {
353
364
  }
354
365
  async function writeDebateDoc(vs,done,val){
355
366
  const lines=['# 验证辩论|'+vs.targetId+'('+vs.targetType+')|'+fmtTime(),'',(done?('**结论**:'+(val===1?'全体一致为真':'全体一致为假')):('**未达成全体一致**,平均概率 '+val.toFixed(2))),'','## 各常驻意见']
356
- for(const [k,v] of Object.entries(vs.verdicts)){ lines.push('### '+k+''+v.verdict+'|'+v.confidence); lines.push(v.reason||''); lines.push('') }
367
+ for(const [k,v] of Object.entries(vs.verdicts)){ lines.push('### '+k+'|正确概率 '+(v.prob!=null?Number(v.prob).toFixed(2):'0.50')); lines.push(v.reason||''); lines.push('') }
357
368
  await writeText('Shared/debates/'+vs.targetId+'.md', lines.join('\n'))
358
369
  }
359
370
  async function writeVerifiedCard(vs,isTrue){
@@ -422,7 +433,9 @@ export function apply(ctx) {
422
433
  const signal = makeSignal(params.activityTimeoutMs||60000)
423
434
  const result = await compaction.compactIfNeeded(agent, 'pressure', signal)
424
435
  if(result && (result.shadowedSeqs||[]).length>0){
425
- r.roundsSinceCompact=0; r.needCompact=false; r.contextPct=Math.min(r.contextPct||15,25)
436
+ // the resident's real session was compacted → its context is now a summary.
437
+ // Flag needCompact so the NEXT wake re-anchors the core rules (they may have been blurred).
438
+ r.roundsSinceCompact=0; r.needCompact=true; r.contextPct=Math.min(r.contextPct||15,25)
426
439
  logActivity('compact', r.rId+' real /compact (shadowed '+result.shadowedSeqs.length+' items, ~'+String(result.shadowedTokenCount||0)+' tokens)')
427
440
  }
428
441
  } catch(e){ /* real compaction unavailable/failed; the soft directive already covers it */ }
@@ -485,8 +498,15 @@ export function apply(ctx) {
485
498
  }
486
499
  if((kind==='verif-ind'||kind==='verif-deb') && verifyState){
487
500
  const v=(parsed&&parsed.vote)||{}
488
- const verdict=String(v.verdict)==='TRUE'?'TRUE':String(v.verdict)==='FALSE'?'FALSE':'UNCERTAIN'
489
- verifyState.verdicts[r.rId]={verdict,confidence:cl(v.confidence!=null?v.confidence:0.5),reason:String(v.reason||parsed.summary||'')}
501
+ // verdict = 0-1 probability the object is TRUE (1=绝对真, 0=绝对假, 0.5=不确定);
502
+ // also accept legacy 'TRUE'/'FALSE' strings.
503
+ let p
504
+ if(typeof v.verdict==='number'){ p=clamp01(v.verdict) }
505
+ else if(/^TRUE$/i.test(String(v.verdict))){ p=1 }
506
+ else if(/^FALSE$/i.test(String(v.verdict))){ p=0 }
507
+ else { p=clamp01(Number(v.confidence)) }
508
+ // verdict is a PURE 0-1 probability (a degree); no binary TRUE/FALSE classification.
509
+ verifyState.verdicts[r.rId]={prob:p,confidence:p,reason:String(v.reason||parsed.summary||'')}
490
510
  await saveAll(); await continueVerifyRound(); return
491
511
  }
492
512
  // normal turn
@@ -510,10 +530,12 @@ export function apply(ctx) {
510
530
 
511
531
  // ---- controls ----
512
532
  async function start({problem,residentCount,seedDirections}){
513
- if(!problem) return {ok:false,message:'problem text required'}
533
+ await loadSettings()
514
534
  currentProject=await readCurrentProject(); if(!currentProject||currentProject==='default'){ currentProject='default'; }
515
535
  await ensureDirs()
516
- problemText=String(problem); problemId=slugify(String(problem).slice(0,40))||'problem'
536
+ if(problem) problemText=String(problem)
537
+ if(!problemText) return {ok:false,message:'problem text required (pass problem, or use vibe_v4_configure first)'}
538
+ problemId=slugify(problemText.slice(0,40))||'problem'
517
539
  if(residentCount) params.residentCount=Number(residentCount)||4
518
540
  running=true; autoDone=false; phase='brainstorm'
519
541
  await writeText('Problems/'+problemId+'.md','# 问题|'+problemId+'\n- ID: '+problemId+'\n- 类型: 问题\n- 状态: 求解中\n- 优先级: 1\n- 依赖: []\n\n## 陈述\n'+problemText+'\n')
@@ -523,7 +545,7 @@ export function apply(ctx) {
523
545
  await saveAll(); return {ok:true,message:'v4 started: '+params.residentCount+' resident(s) brainstorming',project:currentProject}
524
546
  }
525
547
  async function resume(){
526
- currentProject=await readCurrentProject(); await ensureDirs(); await loadAll()
548
+ currentProject=await readCurrentProject(); await ensureDirs(); await loadAll(); await loadSettings()
527
549
  if(phase==='idle' && !running && residents.size===0) return {ok:false,message:'nothing to resume'}
528
550
  // If the persisted State came from a DIFFERENT process (crash/restart), the saved
529
551
  // childIds are stale; clear them so residents re-spawn (their libraries persist on
@@ -544,14 +566,29 @@ export function apply(ctx) {
544
566
  recentActivity: activityLog.slice(-8) } }
545
567
  async function addMember(direction){ const r=newResident(direction||''); await spawnResident(r); return {ok:true,id:r.rId,direction:r.direction} }
546
568
  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} }
547
- function setParams(upd){ for(const k of Object.keys(upd||{})){ if(k in params) params[k]=upd[k] } return {ok:true} }
569
+ function setParams(upd){ for(const k of Object.keys(upd||{})){ if(k in params) params[k]=upd[k] } saveSettings().catch(()=>{}); return {ok:true} }
570
+ // ---- create / configure (no auto-start) + settings-file persistence ----
571
+ async function loadSettings(){ const s=await readJson('State/settings.json'); if(s&&typeof s==='object'){ for(const k of Object.keys(s)){ if(k in params) params[k]=s[k] } } }
572
+ async function saveSettings(){ await writeJson('State/settings.json', params) }
573
+ // Create/configure a project and set params/problem WITHOUT starting any resident.
574
+ // The intended flow: vibe_v4_configure {project?, problem?, params?} → vibe_v4_start {}.
575
+ async function configure(cfg){
576
+ if(cfg && cfg.project && String(cfg.project).trim()) currentProject=String(cfg.project).trim()
577
+ if(cfg && cfg.problem) problemText=String(cfg.problem)
578
+ if(cfg && cfg.params && typeof cfg.params==='object') for(const k of Object.keys(cfg.params)) if(k in params) params[k]=cfg.params[k]
579
+ await writeCurrentProject(); await ensureDirs(); await saveSettings()
580
+ // create the problem card so the project is complete BEFORE the run starts
581
+ if(problemText){ const pid=slugify(problemText.slice(0,40))||'problem'; await writeText('Problems/'+pid+'.md','# 问题|'+pid+'\n- ID: '+pid+'\n- 类型: 问题\n- 状态: 求解中\n- 优先级: 1\n- 依赖: []\n\n## 陈述\n'+problemText+'\n') }
582
+ await saveAll()
583
+ return {ok:true,project:currentProject,problem:problemText?problemText.slice(0,60):'',params:Object.keys(params).map(k=>k+'='+params[k]).join(', ')}
584
+ }
548
585
  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 } await saveAll(); return {ok:true,message:'aborted'} }
549
586
  function setPause(){ clearHeartbeat(); running=false; return {ok:true,message:'paused'} }
550
587
 
551
588
  return {
552
589
  sessionId, running:()=>running, autoDone:()=>autoDone, phase:()=>phase,
553
590
  onResidentEnd, start, resume, status, report, addMember, removeMember, setParams,
554
- setPause, initAbort, postMessage, startMeeting, saveAll, broadcast,
591
+ setPause, initAbort, postMessage, startMeeting, saveAll, broadcast, configure, loadSettings,
555
592
  currentResident:()=>currentResident,
556
593
  residentIdOf:(agent)=>{ const m=residentOfAgent(agent); return m||currentResident },
557
594
  useResident:(id)=>{ currentResident=id },
@@ -575,7 +612,8 @@ export function apply(ctx) {
575
612
  } })
576
613
  }
577
614
  // host/assistant-facing
578
- registerTool('vibe_v4_start','Start V4: spawn N resident subagents (brainstorm then self-organize).',objParams({problem:{type:'string'},residentCount:{type:'integer'},seedDirections:{type:'array',items:{type:'string'}}},['problem']),(s,a)=>s.start(a))
615
+ registerTool('vibe_v4_configure','Create/configure a project: set project name, problem, and params WITHOUT starting a run. Use this FIRST, then vibe_v4_start to actually spawn residents.',objParams({project:{type:'string'},problem:{type:'string'},params:{type:'object'}}),(s,a)=>s.configure(a))
616
+ registerTool('vibe_v4_start','Start V4: spawn N resident subagents (brainstorm then self-organize).',objParams({problem:{type:'string'},residentCount:{type:'integer'},seedDirections:{type:'array',items:{type:'string'}}}),(s,a)=>s.start(a))
579
617
  registerTool('vibe_v4_resume','Resume a persisted V4 run.',objParams({}),(s)=>s.resume())
580
618
  registerTool('vibe_v4_pause','Pause V4.',objParams({}),(s)=>s.setPause())
581
619
  registerTool('vibe_v4_abort','Abort V4 and interrupt residents.',objParams({}),(s)=>s.initAbort())
@@ -608,12 +646,13 @@ export function apply(ctx) {
608
646
 
609
647
  commands.register({
610
648
  name:'v4', description:'control the Vibe Math V4 framework',
611
- input:{hint:'[start|resume|pause|abort|status|report|meeting|members|add|remove|set]'},
649
+ input:{hint:'[configure|start|resume|pause|abort|status|report|meeting|members|add|remove|set]'},
612
650
  handler: async function(inv){
613
651
  const s=getSession(inv&&inv.agent); if(!s) return {kind:'success',text:JSON.stringify({ok:false,error:'no session'})}
614
652
  const line=String(inv&&inv.rawInput?inv.rawInput:'').trim(); const parts=line.split(/\s+/); const cmd=parts[0]||''; const rest=parts.slice(1)
615
653
  let r
616
- if(cmd==='start') r=await s.start({problem:rest.join(' ')})
654
+ if(cmd==='configure') r=await s.configure({project:rest[0]||'', problem:parts.slice(2).join(' ')})
655
+ else if(cmd==='start') r=await s.start({})
617
656
  else if(cmd==='resume') r=await s.resume()
618
657
  else if(cmd==='pause') r=s.setPause()
619
658
  else if(cmd==='abort') r=await s.initAbort()
@@ -623,7 +662,8 @@ export function apply(ctx) {
623
662
  else if(cmd==='members') r={ok:true,residents:s.listResidents()}
624
663
  else if(cmd==='add') r=await s.addMember(rest.join(' '))
625
664
  else if(cmd==='remove') r=await s.removeMember(rest[0]||'')
626
- else r={ok:false,usage:'start|resume|pause|abort|status|report|message|meeting|members|add|remove|set'}
665
+ else if(cmd==='set'){ const upd={}; for(const tok of rest){ const eq=tok.indexOf('='); if(eq>0){ const k=tok.slice(0,eq); const rv=tok.slice(eq+1); const n=Number(rv); upd[k]=Number.isFinite(n)?n:rv } } r=s.setParams(upd) }
666
+ else r={ok:false,usage:'configure|start|resume|pause|abort|status|report|message|meeting|members|add|remove|set'}
627
667
  return {kind:'success',text:JSON.stringify(r,null,2)}
628
668
  },
629
669
  })
@@ -446,4 +446,40 @@ VibeMath/Projects/<project>/
446
446
  ### 5. 主代理放权(减少"主持人"指挥)
447
447
  `agent.cordis.yml` persona 明确:**你的角色是让常驻自组织(hands-off)**。不要注入议程/优先级/分工/验证决定,不要指挥常驻;运行 `start` 后只读 `status/report`、在用户明确要求或团队明显僵死时才 `message`/`meeting`,且只做"促成",不做"决定"。
448
448
 
449
+ ---
450
+
451
+ ## 22. 进一步按哲学打磨(v1.3.9)
452
+
453
+ ### 1. 会议议程来源确认(非 bug)
454
+ 核查确认:之前担心的"主持人式"会议议程,其实是 **r-1 在它的汇报里 `propose_meeting` 字段给出的**,框架据此启动会议。属**常驻自组织发起会议**,符合哲学,无需改。(仅把 `finalizeMeeting` 的日志措辞从"not all spoke / not unanimous"改为准确的"no unanimous solved vote"。)
455
+
456
+ ### 2. 压缩后重申核心规则(治"压缩遗忘规则")
457
+ 常驻的背景/规则只在首轮讲一次;为避免真实 `/compact` 后常驻淡忘规则,现在**每次压缩触发时**(`needCompact`/达阈值)在提示开头**重申一段短的核心规则**(只有 Verified/ 算确立、验证须全组一致、只写自己/只读他人、任务分工团队决定、退出只输出 JSON),其余轮次仍保持极简。
458
+
459
+ ### 3. 验证 `verdict` 明确为 0–1 正确概率
460
+ 验证提示明确:`verdict` ∈ [0,1],**1=绝对为真(判真),0=绝对为假(判假),0.5=完全不确定**;"全体常驻一致判真(正确概率 verdict 为 1)或一致判假(正确概率 verdict 为 0)才算数"。框架把 `verdict` 解析为数值(>0.5→判真,<0.5→判假,=0.5→不确定),未全票时**留库附全组平均正确概率**;辩论录/源卡回写统一用该概率。向后兼容旧的 `"TRUE"/"FALSE"` 字符串。
461
+
462
+ ### 4. 创建项目不再立即启动(先配置后启动)+ settings 文件 + 项目名
463
+ 新增 **`vibe_v4_configure {project?, problem?, params?}`**:**只创建/配置项目(名称、问题、参数),不唤醒任何常驻**;参数持久化到 `State/settings.json`。之后 **`vibe_v4_start {problem?, residentCount?, seedDirections?}`** 才真正启动(若已配置问题可省略)。这样"先设好参数再启动",不再一创建就着急跑。`/v4 configure` 子命令 + 主代理 persona 的 `Main controls` 已同步(`vibe_v4_set` 也持久化到 settings 文件);支持设置**项目名**(`configure.project`)。
464
+
465
+ ---
466
+
467
+ ## 23. verdict 改为纯概率数值 + 全面审计修复(v1.4.0)
468
+
469
+ ### 1. `verdict` 是**纯 0–1 概率数值**(不再二分类)
470
+ 按用户要求,`verdict` 现在**只是一个 0–1 的正确概率**(程度),框架**不再把它分段映射成 TRUE/FALSE/不确定**。判定规则:
471
+ - **仅当全体常驻一致给 `1`(都认为是真)** → 按"真"写入 Verified/;
472
+ - **仅当全体常驻一致给 `0`(都认为是假)** → 按"假"写入 Verified/;
473
+ - **否则**:只作为**概率数值(一种程度)保留在库中**,附全组平均正确概率(`- 概率:` 写该平均值),**不写成真/假**。
474
+
475
+ 相应地:验证提示改为"请给出对该对象为真的正确概率 verdict(一个 0–1 数值,不要给 TRUE/FALSE)";解析/存储/辩论录/源卡回写全用**数值概率**。向后兼容旧 `"TRUE"/"FALSE"`(解析为 1/0)。**注意**:这也意味着"0.97(很高但非 1)"不再算"真",会保留为概率 0.97——这是更严格的"绝对一致"口径。
476
+
477
+ ### 2. 全面审计修复
478
+ - **`resume` 补上 `loadSettings()`**:否则跨进程 resume 后参数会退回默认(settings 不加载)。
479
+ - **`configure` 现在直接写出问题卡**(`Problems/<id>.md`),使"创建项目"在启动前就完整;`start` 仍会幂等重写。
480
+ - **补上缺失的 `/v4 set` 分支**:此前 usage 列了 `set` 但命令处理器没实现,`/v4 set` 会掉到 usage;现支持 `key=value` 解析并 `setParams`(也持久化到 settings)。
481
+ - **真实 `/compact` 后重申规则**:`realCompact` 成功压缩常驻真实会话后,置 `needCompact=true`,使下一次唤醒**重申核心规则**(与软压缩一致),避免真实压缩后常驻淡忘规则。
482
+
483
+
484
+
449
485