dsh-vibe-math 1.3.6 → 1.3.8
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
|
@@ -57,6 +57,10 @@
|
|
|
57
57
|
> 🔧 **v1.3.5 边界 A 落地 + 真实 `/compact`**:`maxParallel` 真正限流(在途上限),`activityTimeoutMs` 作为**心跳门控**(空闲超时才触发 CHECKPOINT 唤醒,推动收敛/停止而非无限烧 token);并用 DSH 真实 `ctx.compaction.compactIfNeeded(常驻 agent, 'pressure', signal)` 压缩常驻自身上下文(回退到自述指令)。详见 §19。
|
|
58
58
|
>
|
|
59
59
|
> 🔧 **v1.3.6 修复 v4 preset 选择后跳回原 preset**:v4 插件的 `apply` 读取 `ctx.subagents/agents/fs/tools/commands` 却**未声明 `inject`**,被 DSH 守卫以"未声明依赖"拒绝 → 组合无法挂载 → 选择后自动回退。已补 `export const inject = [...]`,并把心跳定时器从全局 `setTimeout/clearTimeout`(插件沙箱里不存在)改为 **`timer` 服务(`ctx.timeout`)**。
|
|
60
|
+
>
|
|
61
|
+
> 🔧 **v1.3.7 哲学回归(清晰提示词 + 真实交流群 + 直接写文件)**:常驻首轮注入完整 `contextBrief`(背景/使命、工作模式、文件与格式、工具、规则);会议把其他常驻实际发言(input)转给每个人看,常驻日常轮的 `input` 经 `relayToGroup` 转发到其它常驻邮箱(像群聊);常驻**直接用 fs 写自己的 md**;去固定约束改为团队讨论涌现。详见 §20。
|
|
62
|
+
>
|
|
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。
|
|
60
64
|
|
|
61
65
|
---
|
|
62
66
|
|
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.
|
|
4
|
+
"version": "1.3.8",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "installer.js",
|
|
7
7
|
"exports": {
|
|
@@ -22,19 +22,34 @@
|
|
|
22
22
|
## Vibe Math V4 toolkit
|
|
23
23
|
|
|
24
24
|
This session includes the "Vibe Math V4" persistent self-organizing collaborative
|
|
25
|
-
research framework (fourth-generation architecture).
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
research framework (fourth-generation architecture). It is a REAL research group that
|
|
26
|
+
works by talking: a set of RESIDENT subagents message each other and hold meetings,
|
|
27
|
+
and they decide ALL task allocation, division of labor, priorities, what to verify, and
|
|
28
|
+
when to stop — through their own discussion. There is NO central scheduler assigning
|
|
29
|
+
tasks. Each resident persists its own progress / proposition / method / sub-problem
|
|
30
|
+
library and WRITES those files DIRECTLY (via fs) in a documented format; anyone may READ
|
|
31
|
+
everyone else's files (read-only). Anything is "established" only when ALL residents
|
|
32
|
+
agree (unanimous true or false); otherwise it stays in a library with a probability.
|
|
33
|
+
|
|
34
|
+
The framework is just a facilitator: it relays the group's conversation (a resident's
|
|
35
|
+
`input` is forwarded to the others, and meetings forward everyone's contribution so the
|
|
36
|
+
team genuinely discusses/debates), convenes and records meetings, exposes a shared task
|
|
37
|
+
board, and stops the run only when the whole team agrees the problem is solved.
|
|
38
|
+
|
|
39
|
+
**YOUR ROLE — LET THEM SELF-ORGANIZE (hands-off):** you are NOT a moderator/coordinator.
|
|
40
|
+
Do NOT inject agendas, priorities, division-of-labor, or verification decisions, and do
|
|
41
|
+
NOT direct the residents' work. After `vibe_v4_start`, stay passive: read `vibe_v4_status`
|
|
42
|
+
/ `vibe_v4_report` and summarize in plain language when asked. Use `vibe_v4_message` /
|
|
43
|
+
`vibe_v4_meeting` ONLY when the user explicitly asks you to intervene, or when the group
|
|
44
|
+
is visibly deadlocked (all idle & nothing progressing for a long time) — and even then,
|
|
45
|
+
only relay/nudge the group to decide, never decide for them.
|
|
31
46
|
|
|
32
47
|
Data lives under {{cwd}}/VibeMath/Projects/<project>/:
|
|
33
48
|
Problems/ (original problem card), Progress/<resident>/ (each resident's progress),
|
|
34
|
-
Propos/<resident>/ (each resident's propositions
|
|
35
|
-
Subproblems/<resident>/, Shared/ (meeting transcripts /
|
|
36
|
-
Verified/ (read-only, ONLY after unanimous consensus),
|
|
37
|
-
Reliable/ (references), Notes/.
|
|
49
|
+
Propos/<resident>/ (each resident's propositions, "- ID: p-<id>" / "- 概率:" / "- 价值程度:" ...),
|
|
50
|
+
Methods/<resident>/ (theories/tools), Subproblems/<resident>/, Shared/ (meeting transcripts /
|
|
51
|
+
task board / debates), Verified/ (read-only, ONLY after unanimous consensus),
|
|
52
|
+
State/ (framework-private), Reliable/ (references), Notes/.
|
|
38
53
|
|
|
39
54
|
Main controls:
|
|
40
55
|
- vibe_v4_start {problem, residentCount?, seedDirections?} — spawn residents, brainstorm, begin.
|
|
@@ -104,49 +104,96 @@ export function apply(ctx) {
|
|
|
104
104
|
// ---- resident prompts ----
|
|
105
105
|
function banner(){ const o=[]; for(const [id,r] of residents) o.push('- '+id+'「'+(r.direction||'(未定)')+'」'+r.status+'·轮'+r.rounds); return o.join('\n') }
|
|
106
106
|
async function inboxText(rId){ const mb=mailboxes.get(rId)||[]; if(mb.length===0) return ' (no new messages)\n'; return mb.map(m=>' ['+m.from+'] '+m.content).join('\n')+'\n' }
|
|
107
|
+
function residentLibraries(){
|
|
108
|
+
const base=frameworkRoot()
|
|
109
|
+
return '你的资料库根目录:'+base+'/\n'
|
|
110
|
+
+' Progress/<你>/progress.md —— 你的研究日志(叙述,可追加)。\n'
|
|
111
|
+
+' Propos/<你>/<id>.md —— 你的命题/引理。格式:\n'
|
|
112
|
+
+' - ID: p-<id>; - 状态: 未定论; - 概率: <0-1>; - 价值程度: <0-1>; - 动机用途计划: <为何重要/打算怎么用>\n'
|
|
113
|
+
+' 然后 ## 陈述 <陈述>;## 证明尝试;## 证伪尝试。\n'
|
|
114
|
+
+' Methods/<你>/<id>.md —— 你的理论/方法/工具。格式:- ID: m-<id>; - 状态: 经验; - 可信断言: []; - 价值程度: <0-1>; - 动机用途计划: ...;然后 ## 核心内容;## 定义与记号;## 应用记录;## 改进历史。\n'
|
|
115
|
+
+' Subproblems/<你>/<id>.md —— 你的子问题。格式:- ID: s-<id>; - 状态: 求解中; - 价值程度: <0-1>; - 动机用途计划: ...;然后 ## 陈述;## 进度。\n'
|
|
116
|
+
}
|
|
117
|
+
function toolList(){
|
|
118
|
+
return 'vibe_v4_send_message {to, content} —— 给某常驻发消息(to=all 广播)。\n'
|
|
119
|
+
+'vibe_v4_meeting {agenda} —— 发起/参与会议(框架会把各常驻的实际 input 转给其他人,让大家看到并讨论/辩论)。\n'
|
|
120
|
+
+'vibe_v4_propose_task/claim_task/task_done/list_tasks —— 共享任务板(提议/认领/完成/查看;任务板是你们协调分工的载体)。\n'
|
|
121
|
+
+'vibe_v4_publish_progress/record_proposition/record_method/record_subproblem —— 便捷记录器(可选;推荐直接用 fs 写自己的文件)。\n'
|
|
122
|
+
+'vibe_v4_read_progress {id} —— 只读某常驻的进展。\n'
|
|
123
|
+
+'vibe_v4_list_residents / vibe_v4_list_tasks —— 查看团队组成 / 开放任务。\n'
|
|
124
|
+
+'vibe_v4_report_context {pct} —— 上报上下文占比(框架据此压缩你的上下文)。\n'
|
|
125
|
+
+'fs (read/write/list) —— 读取任意文件;写入你自己的文件(推荐直接用 fs 直接写自己的 md)。\n'
|
|
126
|
+
}
|
|
127
|
+
// A shared, complete context block so a resident always knows the situation: mission,
|
|
128
|
+
// work model, what it can do, which files it owns (+ formats), what others' files are,
|
|
129
|
+
// and that it may READ anyone and WRITE its own directly. level 'full' = initial brief.
|
|
130
|
+
function contextBrief(r, level){
|
|
131
|
+
const s=[]
|
|
132
|
+
s.push('## 背景 —— 你是常驻研究团队的一员')
|
|
133
|
+
s.push('You are resident researcher '+r.rId+'(常驻研究者 '+r.rId+';共 '+params.residentCount+' 位常驻),正在协作解决:')
|
|
134
|
+
s.push(problemText)
|
|
135
|
+
s.push('')
|
|
136
|
+
s.push('这像一个**真实的学术小组**:没有中央调度器、没有外部派活——你们自己通过 **互相发消息 + 开会讨论** 来决定一切:谁做什么、怎么分工、验证什么、何时停止。你的 Round 决定你这一轮做什么;团队的优先级与分工由大家的讨论涌现。')
|
|
137
|
+
s.push('')
|
|
138
|
+
s.push('### 工作模式(会发生什么)')
|
|
139
|
+
s.push('1. 每人有一份持久、全组可见的专属资料库(见下)。')
|
|
140
|
+
s.push('2. 你们自由发消息、开会;**会议会把每个人实际说的话(input)转给其他人**,让你看得到、能回复、能讨论、能辩论。')
|
|
141
|
+
s.push('3. 你独立研究,并**直接用 fs 写入你自己的文件**(按格式),供全组阅读。')
|
|
142
|
+
s.push('4. 任何"已确立"的东西须**全组一致**验证(全真或全假)才作数;否则只是带概率的工作估计。')
|
|
143
|
+
s.push('5. 只有**全组在会议上一致认为原问题已解决**,run 才停止。')
|
|
144
|
+
s.push('')
|
|
145
|
+
s.push('### 你负责的文件(你只写自己的;但可读任何人的)')
|
|
146
|
+
s.push(residentLibraries())
|
|
147
|
+
s.push('其他人把结论/进展写进他们的目录,你就能读到。**你应主动读别人的库**,对齐事实、彼此衔接、避免重复劳动。')
|
|
148
|
+
if(level!=='full'){ s.push('(格式见你最初的说明;直接用 fs 写自己的文件即可。)') }
|
|
149
|
+
s.push('')
|
|
150
|
+
s.push('### 可用工具')
|
|
151
|
+
s.push(toolList())
|
|
152
|
+
s.push('')
|
|
153
|
+
s.push('### 规则')
|
|
154
|
+
s.push('- 只有 Verified/(或卡片标"已验证·真/假")算已确立;其余都是你的实验性工作,请区分"猜想/已知"。')
|
|
155
|
+
s.push('- 验证必须**全组一致**(全真或全假);你只信全票结果。未全票的对象留在库里带概率。')
|
|
156
|
+
s.push('- 你自己决定做什么,但**优先级/分工由团队讨论决定**,不是固定模式。若你认为问题已解决或接近解决,请**发起会议**让团队表决。')
|
|
157
|
+
s.push('- 退出时**只**输出一个 JSON 对象(放在 ```json 代码围栏内;围栏外不要有文字)。')
|
|
158
|
+
return s.join('\n')
|
|
159
|
+
}
|
|
107
160
|
function brainstormPrompt(r){
|
|
108
161
|
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
109
|
-
+
|
|
110
|
-
+(r.direction?('\n\
|
|
111
|
-
+'
|
|
112
|
-
+'
|
|
113
|
-
+'
|
|
114
|
-
+'Reply with ONLY a JSON object
|
|
115
|
-
+'{"summary":"<your insight, one tight paragraph>","solved":false}'
|
|
162
|
+
+contextBrief(r,'full')+'\n'
|
|
163
|
+
+(r.direction?('\n\n你被建议的初始方向(可自行调整/细化):\n'+r.direction+'\n'):'')
|
|
164
|
+
+'## 这是你的第一轮:独立头脑风暴\n'
|
|
165
|
+
+'独立地想清楚:你对这个问题的洞察 / 解决方向 / 关键子问题 / 可能的引理 / 粗略计划。你还未见到其他人,先独立产出。\n'
|
|
166
|
+
+'把有价值的产物**直接用 fs 写进你自己的文件**(按上面格式),并在 summary 里概述你的切入方向与初步结论(标注哪些是猜想、哪些凭你已确证)。\n'
|
|
167
|
+
+'Reply with ONLY a JSON object:\n'
|
|
168
|
+
+'{"summary":"<your insight / direction / rough plan, one tight paragraph>","solved":false}'
|
|
116
169
|
}
|
|
117
170
|
async function normalPrompt(r){
|
|
118
171
|
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
119
|
-
+'
|
|
120
|
-
+'
|
|
121
|
-
+'
|
|
122
|
-
+'
|
|
123
|
-
+'
|
|
124
|
-
+'- call a meeting (vibe_v4_meeting) to coordinate / allocate tasks / propose a verification;\n'
|
|
125
|
-
+'- propose an object for unanimous verification (set propose_verify in your reply);\n'
|
|
126
|
-
+'- report your context usage (vibe_v4_report_context) so the framework compacts you when needed.\n'
|
|
127
|
-
+'You may READ any other resident\'s Progress/Propos/Methods/Subproblems (read-only via vibe_v4_read_progress / fs); you only WRITE your own '+r.rId+' library.\n'
|
|
128
|
-
+'Rules:\n- Only Verified/ is established. Verification requires ALL residents unanimous; you trust only unanimous results.\n'
|
|
129
|
-
+'- If the ORIGINAL problem is solved, set solved=true (we stop only when ALL residents agree).\n'
|
|
130
|
-
+'New items:\n'+ (await inboxText(r.rId))
|
|
131
|
-
+'\nReply with ONLY a JSON object in a ```json fence (no prose outside):\n'
|
|
132
|
-
+'{"summary":"<what you did this round, 1-3 sentences>","solved":false,"propose_verify":"<id|null>","propose_task":"<task title|null>","claim_task":"<task id|null>","contextPct":40}'
|
|
172
|
+
+'Resident researcher '+r.rId+' — 第 '+r.rounds+' 轮。一切由你和团队讨论决定。动手前先**读别人的库**对齐事实、避免重复;把新进展/结论**直接用 fs 写进你自己的文件**;想对团队说的话放 "input"(会转给其他常驻)。\n'
|
|
173
|
+
+'\n团队成员:\n'+banner()+'\n'
|
|
174
|
+
+'New items:\n'+ (await inboxText(r.rId)) +'\n'
|
|
175
|
+
+'Reply with ONLY a JSON object:\n'
|
|
176
|
+
+'{"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}'
|
|
133
177
|
}
|
|
134
178
|
function meetingPrompt(r, st){
|
|
179
|
+
const prior=Object.entries(st.inputs).filter(([k])=>k!==r.rId).map(([k,iv])=>' ['+k+'] '+String(iv.input||iv.summary||'')).join('\n')
|
|
135
180
|
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
136
|
-
+'
|
|
137
|
-
+(st.type==='verify'?('\
|
|
138
|
-
+'\
|
|
139
|
-
+'
|
|
140
|
-
+'
|
|
181
|
+
+'Resident '+r.rId+' — 团队会议进行中。 A meeting is in progress (agenda: '+st.agenda+').'
|
|
182
|
+
+(st.type==='verify'?('\n团队正在验证对象:'+st.targetId+'('+st.targetType+',提出者 '+st.targetOwner+')。请先看他人意见,再给独立判断。'):'')
|
|
183
|
+
+'\n这是一场真实讨论:下面已有人发言(转给你),请先看,然后**加入讨论/补充/反驳/表决**。'
|
|
184
|
+
+(prior?('\n\n### 已有发言(他人 input,已转发给你)\n'+prior):'\n(目前还没人发言,你先说。)')
|
|
185
|
+
+'\n\n你可以:提议任务(propose_task)、认领开放任务(claim_task)、提议验证对象(propose_verify)、或对"原问题是否已解决"表决(voteSolved)。请把**你的实际发言**写进 "input"。'
|
|
186
|
+
+'\nReply with ONLY a JSON object:\n'
|
|
187
|
+
+'{"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}'
|
|
141
188
|
}
|
|
142
189
|
function verifyPrompt(r, vs){
|
|
143
190
|
const others=Object.entries(vs.verdicts).map(([k,v])=>'- '+k+': '+v.verdict+' ('+v.confidence+') '+v.reason).join('\n')
|
|
144
191
|
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
145
|
-
+'
|
|
146
|
-
+'
|
|
147
|
-
+(vs.stage==='debate'?'
|
|
148
|
-
+(vs.stage==='debate'?('
|
|
149
|
-
+'\nReply with ONLY a JSON object
|
|
192
|
+
+'Resident '+r.rId+' — 团队验证。 The group is verifying object '+vs.targetId+'('+vs.targetType+',提出者 '+vs.targetOwner+')。\n'
|
|
193
|
+
+'只有**全体常驻一致判真(或一致判假)**才算数。请给出你**诚实独立的判断**'
|
|
194
|
+
+(vs.stage==='debate'?',并参考他人意见:\n':'。\n')
|
|
195
|
+
+(vs.stage==='debate'&&others?('### 他人意见(已转发给你)\n'+others+'\n'):'')
|
|
196
|
+
+'\nReply with ONLY a JSON object:\n'
|
|
150
197
|
+'{"vote":{"verdict":"TRUE","confidence":0.8,"reason":"<your logic>"}}'
|
|
151
198
|
}
|
|
152
199
|
|
|
@@ -220,6 +267,17 @@ export function apply(ctx) {
|
|
|
220
267
|
for(const [,r] of residents){ const res=await postMessage('facilitator',r.rId,content); if(res&&res.ok) n++ }
|
|
221
268
|
logActivity('broadcast','to '+n+' resident(s)'); await saveAll(); return {ok:true,message:'broadcast to '+n+' resident(s)'}
|
|
222
269
|
}
|
|
270
|
+
// group conversation relay: when a resident "speaks" (input in its round), forward its
|
|
271
|
+
// words to every other resident's inbox so the whole group can see & react — a real group chat.
|
|
272
|
+
async function relayToGroup(from, content){
|
|
273
|
+
const text=String(content||'').trim()
|
|
274
|
+
if(!text) return
|
|
275
|
+
for(const [,r] of residents){
|
|
276
|
+
if(r.rId===from) continue
|
|
277
|
+
const mb=mailboxes.get(r.rId)||[]; mb.push({from,at:now(),content:'[群聊] '+text}); mailboxes.set(r.rId,mb)
|
|
278
|
+
}
|
|
279
|
+
logActivity('relay',from+' → 团队: '+text.slice(0,60)); await saveAll()
|
|
280
|
+
}
|
|
223
281
|
|
|
224
282
|
// ---- meeting ----
|
|
225
283
|
async function startMeeting(agenda,type,targetId){
|
|
@@ -230,15 +288,16 @@ export function apply(ctx) {
|
|
|
230
288
|
}
|
|
231
289
|
async function continueMeetingRound(){
|
|
232
290
|
if(!meetingState) return
|
|
233
|
-
const ids=Array.from(residents.keys()); const
|
|
234
|
-
if(
|
|
235
|
-
// only wake IDLE
|
|
236
|
-
const id=ids.find(x=>meetingState.
|
|
237
|
-
|
|
291
|
+
const ids=Array.from(residents.keys()); const allSpoke=ids.every(id=>meetingState.inputs[id]!==undefined)
|
|
292
|
+
if(allSpoke){ await finalizeMeeting(); return }
|
|
293
|
+
// only wake IDLE un-spoken residents; in-flight ones re-trigger this on end.
|
|
294
|
+
const id=ids.find(x=>meetingState.inputs[x]===undefined && !busy.has(x)); if(!id) return
|
|
295
|
+
const r=residents.get(id)
|
|
238
296
|
await wakeResident(r, meetingPrompt(r,meetingState), 'meeting'); await saveAll()
|
|
239
297
|
}
|
|
240
298
|
async function finalizeMeeting(){
|
|
241
299
|
const st=meetingState
|
|
300
|
+
const ids=Array.from(residents.keys()); const allSpoke=ids.length>0 && ids.every(id=>st.inputs[id]!==undefined)
|
|
242
301
|
const lines=['# 会议 '+st.id+'|'+fmtTime(),'','**议程**:'+st.agenda,'']
|
|
243
302
|
for(const [id,iv] of Object.entries(st.inputs)){ lines.push('### '+id); lines.push(iv.input||''); lines.push('') }
|
|
244
303
|
await writeText('Shared/meetings/'+st.id+'.md', lines.join('\n'))
|
|
@@ -251,8 +310,8 @@ export function apply(ctx) {
|
|
|
251
310
|
if(iv.propose_verify) pendingVerify={targetId:iv.propose_verify,targetType:guessTargetType(iv.propose_verify),proposer:id,at:now()}
|
|
252
311
|
}
|
|
253
312
|
const votes=Object.values(st.inputs).map(x=>x.voteSolved).filter(v=>typeof v==='boolean')
|
|
254
|
-
const allSolved=votes.length>0 && votes.every(v=>v===true)
|
|
255
|
-
logActivity('meeting', 'concluded'+(allSolved?' → ALL agree solved':''))
|
|
313
|
+
const allSolved = allSpoke && votes.length>0 && votes.every(v=>v===true)
|
|
314
|
+
logActivity('meeting', 'concluded'+(allSolved?' → ALL agree solved':' (not all spoke / not unanimous)'))
|
|
256
315
|
if(allSolved){ running=false; autoDone=true; phase='done'; logActivity('stop','all residents agree: problem solved'); await saveAll(); return }
|
|
257
316
|
meetingState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
|
|
258
317
|
}
|
|
@@ -261,33 +320,34 @@ export function apply(ctx) {
|
|
|
261
320
|
async function beginVerify(pv){
|
|
262
321
|
clearHeartbeat()
|
|
263
322
|
pendingVerify=null
|
|
264
|
-
verifyState={targetId:pv.targetId,targetType:pv.targetType,stage:'independent',round:0,asked:[],verdicts:{},transcript:[]}
|
|
323
|
+
verifyState={targetId:pv.targetId,targetType:pv.targetType,targetOwner:pv.proposer||'',stage:'independent',round:0,asked:[],verdicts:{},transcript:[]}
|
|
265
324
|
logActivity('verify','debate begin: '+pv.targetId+' ('+pv.targetType+')'); await saveAll(); await scheduleNext()
|
|
266
325
|
}
|
|
267
326
|
async function continueVerifyRound(){
|
|
268
327
|
if(!verifyState) return
|
|
269
|
-
const ids=Array.from(residents.keys()); const
|
|
270
|
-
if(
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
verifyState.asked.push(id); const r=residents.get(id)
|
|
328
|
+
const ids=Array.from(residents.keys()); const allVoted=ids.every(id=>verifyState.verdicts[id]!==undefined)
|
|
329
|
+
if(allVoted){ await finalizeVerify(); return }
|
|
330
|
+
const id=ids.find(x=>verifyState.verdicts[x]===undefined && !busy.has(x)); if(!id) return
|
|
331
|
+
const r=residents.get(id)
|
|
274
332
|
await wakeResident(r, verifyPrompt(r,verifyState), verifyState.stage==='independent'?'verif-ind':'verif-deb'); await saveAll()
|
|
275
333
|
}
|
|
276
334
|
async function finalizeVerify(){
|
|
277
|
-
const vs=verifyState; const
|
|
278
|
-
const
|
|
279
|
-
const
|
|
335
|
+
const vs=verifyState; const expected=Array.from(residents.keys()).length
|
|
336
|
+
const allVoted = expected>0 && Object.keys(vs.verdicts).length>=expected
|
|
337
|
+
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')
|
|
280
340
|
if(allTrue||allFalse){ await closeVerify(vs,allTrue); return }
|
|
281
341
|
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 }
|
|
282
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
|
|
283
|
-
await writeDebateDoc(vs,false,avg); await rewriteSourceProb(vs.targetId, avg); logActivity('verify',vs.targetId+' NOT unanimous → kept unverified (avg '+avg.toFixed(2)+')')
|
|
343
|
+
await writeDebateDoc(vs,false,avg); await rewriteSourceProb(vs.targetId, avg, vs.targetOwner); logActivity('verify',vs.targetId+' NOT unanimous → kept unverified (avg '+avg.toFixed(2)+')')
|
|
284
344
|
verifyState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
|
|
285
345
|
}
|
|
286
346
|
async function closeVerify(vs,isTrue){
|
|
287
347
|
await writeDebateDoc(vs,true,isTrue?1:0)
|
|
288
348
|
const target=vs.targetId
|
|
289
349
|
await writeVerifiedCard(vs,isTrue)
|
|
290
|
-
await rewriteSource(target,isTrue)
|
|
350
|
+
await rewriteSource(target,isTrue,vs.targetOwner)
|
|
291
351
|
logActivity('verify',target+' → Verified ('+(isTrue?'真':'假')+') by unanimous consensus')
|
|
292
352
|
verifyState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
|
|
293
353
|
}
|
|
@@ -303,27 +363,27 @@ export function apply(ctx) {
|
|
|
303
363
|
const text='# 已验证|'+vs.targetId+'\n- ID: '+vs.targetId+'\n- 类型: '+type+'\n- 结论: '+(isTrue?'真':'假')+'\n- 概率: '+(isTrue?1:0)+'\n- 来源: 全体常驻一致\n## 陈述\n参见来源卡。\n'
|
|
304
364
|
await writeText('Verified/'+dir+'/'+vs.targetId+'.md', text)
|
|
305
365
|
}
|
|
306
|
-
async function findSourceRel(target){
|
|
307
|
-
|
|
308
|
-
|
|
366
|
+
async function findSourceRel(target, owner){
|
|
367
|
+
// Prefer the OWNER's library (avoids id collisions across residents), then others.
|
|
368
|
+
const order = owner ? [owner, ...Array.from(residents.keys()).filter(k=>k!==owner)] : Array.from(residents.keys())
|
|
369
|
+
for(const rid of order){
|
|
309
370
|
for(const base of ['Propos','Methods','Subproblems']){
|
|
310
|
-
const cand=base+'/'+rid+'/'+target+'.md'; if((await readText(cand))!==undefined){
|
|
371
|
+
const cand=base+'/'+rid+'/'+target+'.md'; if((await readText(cand))!==undefined){ return cand }
|
|
311
372
|
}
|
|
312
|
-
if(rel) break
|
|
313
373
|
}
|
|
314
|
-
return
|
|
374
|
+
return 'Propos/'+target+'.md'
|
|
315
375
|
}
|
|
316
376
|
// non-unanimous verification: keep the object in its library but write back the
|
|
317
377
|
// average probability (design §8: "留库附概率"), so the card reflects the consensus estimate.
|
|
318
|
-
async function rewriteSourceProb(target,prob){
|
|
319
|
-
const rel=await findSourceRel(target)
|
|
378
|
+
async function rewriteSourceProb(target,prob,owner){
|
|
379
|
+
const rel=await findSourceRel(target,owner)
|
|
320
380
|
let text=(await readText(rel))||''
|
|
321
381
|
text=text.replace(/(^|\n)- 概率:.*/m,'$1- 概率: '+Number(prob).toFixed(2))
|
|
322
382
|
await writeText(rel,text)
|
|
323
383
|
}
|
|
324
|
-
async function rewriteSource(target,isTrue){
|
|
384
|
+
async function rewriteSource(target,isTrue,owner){
|
|
325
385
|
// find & update the source card status/prob; best effort across per-resident libs
|
|
326
|
-
const rel=await findSourceRel(target)
|
|
386
|
+
const rel=await findSourceRel(target,owner)
|
|
327
387
|
let text=(await readText(rel))||''
|
|
328
388
|
text=text.replace(/(^|\n)- 状态:.*/m,'$1'+(isTrue?'- 状态: 已验证·真':'- 状态: 已验证·假'))
|
|
329
389
|
.replace(/(^|\n)- 概率:.*/m,'$1'+(isTrue?'- 概率: 1':'- 概率: 0'))
|
|
@@ -338,11 +398,9 @@ export function apply(ctx) {
|
|
|
338
398
|
// of infinite token-burning, matching the "framework never assigns work" philosophy.
|
|
339
399
|
function heartbeatPrompt(r){
|
|
340
400
|
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
341
|
-
+'
|
|
342
|
-
+'
|
|
343
|
-
+'
|
|
344
|
-
+'(propose_verify), or set solved=true so the group can reach a decision — do NOT produce filler work.\n'
|
|
345
|
-
+'\nReply with ONLY a JSON object (```json fence):\n'
|
|
401
|
+
+'Resident researcher '+r.rId+' — CHECKPOINT(空闲):团队在等待方向。'
|
|
402
|
+
+'请用一句话说明你下一步做什么;若你已无产出、或认为问题已解决/接近解决,请**提议开会(propose_meeting)**、**提议验证(propose_verify)**、或**声明 solved=true**,让团队能做出决定——不要产出填充性工作。\n'
|
|
403
|
+
+'Reply with ONLY a JSON object:\n'
|
|
346
404
|
+'{"summary":"<what you do next or a declaration>","solved":false,"propose_verify":"<id|null>","propose_meeting":"<agenda|null>","claim_task":"<id|null>"}'
|
|
347
405
|
}
|
|
348
406
|
function clearHeartbeat(){ if(heartbeatDisposer!==null){ try{ heartbeatDisposer() }catch(e){} heartbeatDisposer=null } }
|
|
@@ -438,6 +496,9 @@ export function apply(ctx) {
|
|
|
438
496
|
if(typeof parsed.contextPct==='number'){ r.contextPct=clPct(parsed.contextPct) }
|
|
439
497
|
if(parsed.compacted===true || (r.needCompact && parsed.summary)){ r.contextSeed=String(parsed.summary||''); r.contextPct=Math.min(r.contextPct||15,25); r.roundsSinceCompact=0; r.needCompact=false; logActivity('compact',r.rId+' consolidated context') }
|
|
440
498
|
if(parsed.propose_verify) pendingVerify={targetId:parsed.propose_verify,targetType:guessTargetType(parsed.propose_verify),proposer:r.rId,at:now()}
|
|
499
|
+
// group-conversation relay: the resident may choose to speak to the whole team (input) —
|
|
500
|
+
// forward it to the others so this is a real discussion group, not private monologues.
|
|
501
|
+
if(typeof parsed.input==='string' && parsed.input.trim()) await relayToGroup(r.rId, parsed.input.trim())
|
|
441
502
|
// task actions via reply (a resident may propose or claim a task in its round)
|
|
442
503
|
if(parsed.propose_task) await proposeTask(parsed.propose_task, parsed.task_desc||'', r.rId)
|
|
443
504
|
if(parsed.claim_task) await claimTask(parsed.claim_task, r.rId)
|
|
@@ -398,3 +398,52 @@ VibeMath/Projects/<project>/
|
|
|
398
398
|
|
|
399
399
|
> 局限:v4 的 mock 测试里 `compaction` 为 undefined,故这条**只在真实 DSH 上生效**;需在真实运行体确认 `ctx.compaction` 可用、且会话为常驻自身 session、模型已配 `contextWindow`。部署前请在当前运行 DSH 上验证。`claim_write`/`release_write` 仍保留为占位(常驻专属目录无写冲突)。
|
|
400
400
|
|
|
401
|
+
---
|
|
402
|
+
|
|
403
|
+
## 20. 哲学回归:清晰提示词 + 真实交流群 + 直接写文件(v1.3.7)
|
|
404
|
+
|
|
405
|
+
按用户哲学("以通过交流群自组织各自任务/自组织推动项目为准,以模拟现实真实合作交流推动任务为准")重做常驻的认知与协作机制:
|
|
406
|
+
|
|
407
|
+
### 1. 提示词/上下文足够清晰完整
|
|
408
|
+
新增共享的 `contextBrief(r, level)`,注入到每个常驻的每轮提示里,统一说明:
|
|
409
|
+
- **背景/使命**:你是常驻研究团队的一员,正在协作解决 <问题>;像真实学术小组一样,**没有中央调度/外部派活**,一切由你们讨论决定。
|
|
410
|
+
- **工作模式/会发生什么**:每人有持久全组可见的专属资料库;自由发消息/开会;会议把每人的实际发言(input)转给其他人;独立研究并**直接用 fs 写自己的文件**;"已确立"须全组一致;只有全组一致认为已解决才停止。
|
|
411
|
+
- **你负责的文件与格式**:`residentLibraries()` 列出 Progress/<你>/、Propos/<你>/、Methods/<你>/、Subproblems/<你>/ 及每个文件的确切字段格式(如 `- ID:`、`- 概率:`、`- 价值程度:`、`- 动机用途计划:`、`## 陈述` 等);强调**只写自己、可读任何人的**并应主动读别人的库对齐事实。
|
|
412
|
+
- **可用工具及其功能**:`toolList()` 逐个说明 `vibe_v4_*` 各工具做什么,及 fs(读取任意文件/写自己的文件)。
|
|
413
|
+
- **规则**:仅 Verified/ 算确立、验证须全组一致、优先级/分工由团队讨论决定、退出只输出一个 JSON 对象。
|
|
414
|
+
|
|
415
|
+
### 2. 交流群:会话内容互相转发(真正商量)
|
|
416
|
+
- **会议=真实讨论**:`meetingPrompt` 把"其他常驻已发的 input(框架已转发给你)"注入,让每个人看到别人说了什么、能补充/反驳/表决,而不是各说各话。
|
|
417
|
+
- **常驻发言=群聊转发**:常驻在日常轮里给 `input`(想对团队说的话)时,框架 `relayToGroup` 把该发言**转发到其它常驻的邮箱**(下次唤醒时被看到),让团队的交流像一场群聊。
|
|
418
|
+
- 任务分工、优先级由这种讨论涌现;stop-vote 也发生在会议上(全票 solved 才停)。
|
|
419
|
+
|
|
420
|
+
### 3. 直接操作文件(不必用 vibemath 命令)
|
|
421
|
+
提示词明确:"把进展/结论**直接用 fs 写进你自己的文件**(按上面的格式供全组阅读)";`vibe_v4_publish_progress/record_*` 只是便捷记录器、**不是必需**。常驻自组织写自己的 md,框架据文件读取/索引/验证。
|
|
422
|
+
|
|
423
|
+
### 4. 自组织优先,非固定模式约束
|
|
424
|
+
删除"typical actions"式枚举,改为"你自己决定做什么;优先级/分工由团队讨论决定"。仍保留 JSON 回复里 `propose_verify/propose_meeting/claim_task/voteSolved/solved` 作为框架可执行的**控制通道**,但讨论内容走 `input`/会议转发。
|
|
425
|
+
|
|
426
|
+
> 测试:`selfdrive-v4.mjs` 21/21;`e2e-v4-fixes.test.mjs` 17/17(T5 提示词完整性、T6 群聊转发、T7 背景只讲一次)。
|
|
427
|
+
|
|
428
|
+
---
|
|
429
|
+
|
|
430
|
+
## 21. 基于真实测试的诊断修复(v1.3.8)
|
|
431
|
+
|
|
432
|
+
对一次真实 4 常驻 run(HRT 猜想)的会话记录做了全面诊断,修复以下违反哲学的问题:
|
|
433
|
+
|
|
434
|
+
### 1. 共识验证真正做到"全体一致"
|
|
435
|
+
此前 `finalizeVerify` 只看"投过票的人是否一致"——实测 `p-r1-04` 只有 r-1/r-3 两人投票(r-2/r-4 未投)却被判"全体一致为真"(2/4)。现改为:**只有当全体在册常驻都投了票(`verdicts` 覆盖全部 resident)才可能判"一致"**;否则进入辩论,或超轮后**保留为未定论(不回写 Verified)**。若某常驻一直忙/未投,则该对象**不会**被记为 Verified·真/假。
|
|
436
|
+
|
|
437
|
+
### 2. 会议必须全体发言
|
|
438
|
+
`continueMeetingRound` 改为按"是否已发言(`inputs` 覆盖全部 resident)"判定收口,而非按"是否被问过"。**只要还有常驻没发言,会议就继续等它**;`allSolved`(全票 solved→停止)也要求**全员发言且全票 true**。这样分工/停止表决不会被"缺席成员"带偏。
|
|
439
|
+
|
|
440
|
+
### 3. 背景只在第一轮讲一次(不再每轮重复,省上下文)
|
|
441
|
+
`contextBrief`(背景/使命/工作模式/文件与格式/工具/规则)现在**只在 `brainstormPrompt`(首轮)注入完整版一次**;之后的 normal/meeting/verify/CHECKPOINT 只用**极简的当前状态**(researcher id + 轮次 + 团队成员 + 通知 + JSON 回复),**不再重复那段长背景**,显著减少上下文占用。
|
|
442
|
+
|
|
443
|
+
### 4. 验证目标按"提出者"精确定位
|
|
444
|
+
`pendingVerify` 记录 `proposer`,`beginVerify` 存入 `targetOwner`;`findSourceRel` **优先在提出者的库里找**源卡(避免同名 id 跨常驻撞车,例如 r-3 的 `p-004` vs r-1 的 `p-r1-04`);验证提示里标注"(提出者 <owner>)"让常驻明确在验哪个对象。
|
|
445
|
+
|
|
446
|
+
### 5. 主代理放权(减少"主持人"指挥)
|
|
447
|
+
`agent.cordis.yml` persona 明确:**你的角色是让常驻自组织(hands-off)**。不要注入议程/优先级/分工/验证决定,不要指挥常驻;运行 `start` 后只读 `status/report`、在用户明确要求或团队明显僵死时才 `message`/`meeting`,且只做"促成",不做"决定"。
|
|
448
|
+
|
|
449
|
+
|