dsh-vibe-math 1.2.5 → 1.3.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
|
@@ -1,19 +1,20 @@
|
|
|
1
|
-
# Vibe Mathematics —
|
|
1
|
+
# Vibe Mathematics — 多代理数学问题求解与验证框架(四架构)
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/dsh-vibe-math)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://github.com/ChongCyrus/Vibe-Mathematics)
|
|
6
6
|
|
|
7
|
-
> 运行在 **DeepSeek Harness** 内的一组 **agent preset**(`vibe-math-v1` / `vibe-math-v2` / `vibe-math-v3`),
|
|
8
|
-
>
|
|
9
|
-
>
|
|
10
|
-
> **💡 `vibe-math-v2` 与 `vibe-math-v3`
|
|
7
|
+
> 运行在 **DeepSeek Harness** 内的一组 **agent preset**(`vibe-math-v1` / `vibe-math-v2` / `vibe-math-v3` / `vibe-math-v4`),
|
|
8
|
+
> 用多代理协作自动求解数学问题并对结论做多代理交叉验证。四个预设共享「**断点续跑**、
|
|
9
|
+
> **中途人工干预**、**进度汇报**、**自然语言驱动**」底座能力,但采用四代不同的求解架构:
|
|
10
|
+
> **💡 `vibe-math-v2` 与 `vibe-math-v3` 同级主推**——两者都是成熟可用、正在维护的主推架构,根据你的实际需求自行选择(详见下方「怎么选」);`vibe-math-v4` 是最新的「常驻自组织合作研究」架构(实验性)。
|
|
11
11
|
>
|
|
12
12
|
> - **`vibe-math-v1`(经典流水线)⚠️ 将弃用**:「广度探索 → 深度迭代 → 交叉验证 → 知识沉淀」闭环;
|
|
13
13
|
> - **`vibe-math-v2`(概率驱动 · JSON 数据层)✅ 主推**:`qs.json` 问题清单 + `Propos/` 命题库 + 概率驱动调度 + 代码启发式调度;
|
|
14
14
|
> - **`vibe-math-v3`(第三代 · 论文式 md + 规划代理 + 方法库)✅ 主推**:全部知识以 **Markdown 论文/研究报告式** 存储与续写(`Problems/` 问题清单+依赖+来源动机、`Progress/` 研究日志、`Propos/` 命题库、`Methods/` 通用理论发明库、`Verified/` 绝对可信);调度前由**规划代理**自主制定接下来 N 步计划;解决过程中发明的理论/框架/工具/方法/思想由 **Method Keeper** 沉淀为可复用方法体系(如发明群论、泛函分析那样)。
|
|
15
|
+
> - **`vibe-math-v4`(第四代 · 常驻自组织合作研究)🧪 实验性**:一组**持久化常驻子代理**互相**留言 + 开会**,自主决定一切任务安排(无中央调度);各自沉淀进度/命题/方法/子问题库并互相查阅;验证**仅当全体常驻一致(真 或 假)**才写入 `Verified/`,否则留库附概率;上下文达阈值自动 `/compact`;仅当全体一致认为原问题已解决才停止。
|
|
15
16
|
|
|
16
|
-
安装本插件包(或手动复制预设)后,DSH
|
|
17
|
+
安装本插件包(或手动复制预设)后,DSH 的预设选择器里会出现**四个** agent preset。
|
|
17
18
|
|
|
18
19
|
---
|
|
19
20
|
|
|
@@ -39,6 +40,14 @@
|
|
|
39
40
|
|
|
40
41
|
**一句话流水线**:全部知识以 **Markdown 论文/研究报告式**存储与续写(`Problems/` 问题清单含依赖/后生问题来源动机、`Progress/` 研究日志按方向按轮续写、`Propos/` 命题库、`Methods/` 通用理论发明库、`Verified/` 绝对可信)→ 调度前调度器构造状态简报并调用**规划代理**,规划代理一次性安排接下来 N 步(spawn solver/verifier/explorer/method-keeper、interrupt、promote、wait),代码校验后执行(超出并发的动作排队跨 tick 消费;规划失败自动回退 v2 式启发式)→ 验证器独立审查→辩论→**近共识裁决**(同侧且均值 ≥0.85/≤0.15 取均值,修复 v2 flat 误判)→ 概率=1 收口并生成 `Verified/` 卡 → 求解器的 `methods_used`/`new_inventions` 上报由 **Method Keeper** 沉淀/完善方法库(可组成体系层级、跨项目复用)。
|
|
41
42
|
|
|
43
|
+
### Vibe Math V4(常驻自组织合作研究)🧪 实验性
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+
**一句话流水线**:起始产生 N 个**常驻子代理**(continuable,持久上下文)先各自头脑风暴、产出初始见解/方向 → 此后**所有任务安排由它们互相留言 + 集体开会自主决定**(框架只做消息总线/会议/任务板/产物沉淀,**绝不分配任务**);每个常驻把有价值的产物按**价值程度 / 动机用途计划 / 自身概率估计**沉淀到**自己**的 `Progress/<id>/`、`Propos/<id>/`、`Methods/<id>/`、`Subproblems/<id>/` 库,并**可互相阅读**;验证由它们**自行商议**发起,**仅当全体常驻一致(真或假)**才写入 `Verified/`,否则留库附概率;常驻上下文量达阈值(默认 66%)自动 `/compact`;**仅当全体一致认为原问题已解决**才停止;可随时人工干预/增开/关闭常驻,支持断点续跑。
|
|
48
|
+
|
|
49
|
+
> 说明:V4 去掉 v3 的中央规划器与确定性角色(explorer/solver/verifier/planner/method-keeper),把"研究者"本身作为主体。详见 `vibe-math-v4/实现方案.md`。
|
|
50
|
+
|
|
42
51
|
---
|
|
43
52
|
|
|
44
53
|
## ✨ 功能特色
|
|
@@ -118,17 +127,19 @@ dsh plugin --profile <你的 profile> add github:ChongCyrus/Vibe-Mathematics
|
|
|
118
127
|
>
|
|
119
128
|
> **⚠️ `vibe-math-v1` 是早期流水线架构,仅作参考/兼容保留,可能在将来的版本中被遗弃、不再维护。** 新项目请直接使用 v2 或 v3。
|
|
120
129
|
|
|
121
|
-
| | **v1(经典 · 将弃用)** | **v2(概率驱动 · 主推)** | **v3(论文式 md · 主推)** |
|
|
122
|
-
|
|
123
|
-
| 定位 | 早期流水线架构(保留兼容) | **主推**(JSON 数据层) | **主推**(第三代) |
|
|
124
|
-
| 核心思想 | 流水线:拆方向 → 逐方向求解 → 拆最小单元 → 多验证器辩论 → 晋升 `Verified/` | 概率驱动:`qs.json` 问题 + `Propos/` 命题库,按「正确概率 / 价值」调度 | **论文式 md 知识库 + 规划代理调度 + 通用理论发明库** |
|
|
125
|
-
| 数据 | `qs/qs.csv` + `Progress_Logs/` | `qs/qs.json` + `Propos/<分类>_Propos.json` + `Reliable/` | `Problems/` + `Progress/` + `Propos/` + `Methods/`(全部 md,软规范锚点 + 自由叙述)+ `Verified/` |
|
|
126
|
-
| 角色 | brainstorm / solver / derive / verifier / decider | explorer → 逐方向 solver → verifier | **planner(规划代理)** → explorer → 逐方向 solver → verifier → **method-keeper(方法整理代理)** |
|
|
127
|
-
| 调度方式 | 代码流水线 | 代码启发式(优先级 + 概率) | **规划代理产出 N 步计划**(校验后执行,失败回退启发式) |
|
|
128
|
-
| 收口规则 | 验证通过晋升 `Verified/`,decider 判定解决 | 解法/证明达概率 `1` 即收口,`never` 永不调度 | 同 v2(近共识裁决修复 flat 误判) |
|
|
129
|
-
|
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
| | **v1(经典 · 将弃用)** | **v2(概率驱动 · 主推)** | **v3(论文式 md · 主推)** | **v4(常驻自组织 · 实验)** |
|
|
131
|
+
|---|---|---|---|---|
|
|
132
|
+
| 定位 | 早期流水线架构(保留兼容) | **主推**(JSON 数据层) | **主推**(第三代) | **实验性**(第四代) |
|
|
133
|
+
| 核心思想 | 流水线:拆方向 → 逐方向求解 → 拆最小单元 → 多验证器辩论 → 晋升 `Verified/` | 概率驱动:`qs.json` 问题 + `Propos/` 命题库,按「正确概率 / 价值」调度 | **论文式 md 知识库 + 规划代理调度 + 通用理论发明库** | **持久化常驻子代理自组织**:互相留言 + 开会决定一切任务,无中央调度 |
|
|
134
|
+
| 数据 | `qs/qs.csv` + `Progress_Logs/` | `qs/qs.json` + `Propos/<分类>_Propos.json` + `Reliable/` | `Problems/` + `Progress/` + `Propos/` + `Methods/`(全部 md,软规范锚点 + 自由叙述)+ `Verified/` | `Problems/` + **按常驻 id 归属**的 `Progress|Propos|Methods|Subproblems/<id>/` + `Shared/`(会议/任务板/辩论)+ `Verified/` |
|
|
135
|
+
| 角色 | brainstorm / solver / derive / verifier / decider | explorer → 逐方向 solver → verifier | **planner(规划代理)** → explorer → 逐方向 solver → verifier → **method-keeper(方法整理代理)** | **N 个常驻研究者**(continuable),由它们互相通信/开会分工,无固定角色 |
|
|
136
|
+
| 调度方式 | 代码流水线 | 代码启发式(优先级 + 概率) | **规划代理产出 N 步计划**(校验后执行,失败回退启发式) | **无中央调度**:任务由常驻互相留言/开会(框架只做媒介,不指派) |
|
|
137
|
+
| 收口规则 | 验证通过晋升 `Verified/`,decider 判定解决 | 解法/证明达概率 `1` 即收口,`never` 永不调度 | 同 v2(近共识裁决修复 flat 误判) | **仅当全体常驻一致(真 或 假)**才写入 `Verified/`,否则留库附概率 |
|
|
138
|
+
| 停止 | 全解或卡死 | 全解或卡死 | 全解/无候选 | **仅当全体常驻一致认为原问题已解决**才停止 |
|
|
139
|
+
| 上下文 | 无 | 无 | 无 | **常驻上下文达阈值自动 `/compact`**(可调) |
|
|
140
|
+
| 特设能力 | 子问题分支(Aux_Hypothesis) | 命题「价值/关键性」自动晋升问题清单;`reportMode file/push/both`;`priorityAdjust` | **方法库沉淀循环**(`methods_used`/`new_inventions` → Method Keeper);**计划审批门/方法晋升门**;**项目锁**;后生问题「来源与动机」一等公民 | **常驻各自沉淀 + 互相阅读**;**全体一致验证**;**随时增开/关闭常驻、留言干预**;**断点续跑** |
|
|
141
|
+
|
|
142
|
+
四者都支持:断点续跑(`vibe_math_resume` / `vibe_v4_resume`)、人工/自动模式切换、`vibe_math_*` / `vibe_v4_*` 工具集与 `/vibe` `/v4` 命令、按项目隔离、子代理权限调控。**v2 与 v3 均为同级主推**——偏好结构化 JSON 数据与确定性调度选 v2,偏好论文式 md、规划代理与理论发明库选 v3;v4 是最新的「常驻自组织合作研究」实验架构。
|
|
132
143
|
|
|
133
144
|
---
|
|
134
145
|
|
package/installer.js
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
// dsh-vibe-math merged bundle installer — VERSIONED AUTO-UPDATE.
|
|
2
2
|
// When this bundle is installed (e.g. `dsh plugin add dsh-vibe-math` or from the
|
|
3
|
-
// dsh-market), this plugin copies ALL
|
|
4
|
-
// the DSH preset root, so the user immediately gets
|
|
3
|
+
// dsh-market), this plugin copies ALL FOUR agent presets out of the package into
|
|
4
|
+
// the DSH preset root, so the user immediately gets four presets in the picker:
|
|
5
5
|
// vibe-math-v1/ (classic pipeline architecture)
|
|
6
6
|
// vibe-math-v2/ (probability-driven architecture)
|
|
7
7
|
// vibe-math-v3/ (THIRD-generation: paper-style Markdown knowledge base +
|
|
8
8
|
// planner-agent scheduling + universal theory/method library)
|
|
9
|
+
// vibe-math-v4/ (FOURTH-generation: persistent self-organizing resident
|
|
10
|
+
// subagents — message bus / meetings / unanimous-consensus
|
|
11
|
+
// verification / per-resident libraries) [new]
|
|
9
12
|
//
|
|
10
13
|
// UPDATE POLICY (state recorded in <presetRoot>/.vibe-math-installed.json):
|
|
11
14
|
// - baseline (no state file — e.g. upgrading from an installer that predates
|
|
@@ -43,6 +46,11 @@ const PRESETS = [
|
|
|
43
46
|
dst: 'vibe-math-v3',
|
|
44
47
|
files: ['agent.cordis.yml', 'preset.yml', 'vibe-math-v3.js', '实现方案.md'],
|
|
45
48
|
},
|
|
49
|
+
{
|
|
50
|
+
src: 'vibe-math-v4',
|
|
51
|
+
dst: 'vibe-math-v4',
|
|
52
|
+
files: ['agent.cordis.yml', 'preset.yml', 'vibe-math-v4.js', '实现方案.md'],
|
|
53
|
+
},
|
|
46
54
|
]
|
|
47
55
|
|
|
48
56
|
const STATE_FILE = '.vibe-math-installed.json'
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vibe-math",
|
|
3
|
-
"description": "Multi-agent mathematical problem-solving & verification frameworks for DeepSeek Harness —
|
|
4
|
-
"version": "1.
|
|
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.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "installer.js",
|
|
7
7
|
"exports": {
|
|
@@ -24,7 +24,11 @@
|
|
|
24
24
|
"vibe-math-v3/agent.cordis.yml",
|
|
25
25
|
"vibe-math-v3/preset.yml",
|
|
26
26
|
"vibe-math-v3/vibe-math-v3.js",
|
|
27
|
-
"vibe-math-v3/实现方案.md"
|
|
27
|
+
"vibe-math-v3/实现方案.md",
|
|
28
|
+
"vibe-math-v4/agent.cordis.yml",
|
|
29
|
+
"vibe-math-v4/preset.yml",
|
|
30
|
+
"vibe-math-v4/vibe-math-v4.js",
|
|
31
|
+
"vibe-math-v4/实现方案.md"
|
|
28
32
|
],
|
|
29
33
|
"license": "MIT",
|
|
30
34
|
"keywords": [
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# The `vibe-math-v4` agent preset: the full coding agent (`standard`), plus the
|
|
2
|
+
# FOURTH-generation "persistent self-organizing collaborative research" framework
|
|
3
|
+
# (see 实现方案.md): a set of PERSISTENT resident subagents that decide ALL task
|
|
4
|
+
# allocation among themselves (message/meeting), persist their own progress /
|
|
5
|
+
# proposition / method / sub-problem libraries, verify ONLY by unanimous
|
|
6
|
+
# consensus (else keep as unverified with a probability), self-compact at a
|
|
7
|
+
# context threshold, and stop only when all residents agree the original problem
|
|
8
|
+
# is solved. The framework is a FACILITATOR (message bus / meeting / persist /
|
|
9
|
+
# consensus-verify / context management / resume) — it NEVER assigns tasks.
|
|
10
|
+
#
|
|
11
|
+
# The vibe-math-v4 plugin row consumes HOST subagents/agents/fs/tools/commands
|
|
12
|
+
# services and publishes nothing, so it needs no isolate realm.
|
|
13
|
+
|
|
14
|
+
# ── identity ────────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
- id: persona
|
|
17
|
+
name: '@deepseek-ai/dsh-persona'
|
|
18
|
+
config:
|
|
19
|
+
text: |-
|
|
20
|
+
You are a coding agent powered by the {{model}} model. Your working directory is {{cwd}}.
|
|
21
|
+
|
|
22
|
+
## Vibe Math V4 toolkit
|
|
23
|
+
|
|
24
|
+
This session includes the "Vibe Math V4" persistent self-organizing collaborative
|
|
25
|
+
research framework (fourth-generation architecture). Instead of a central scheduler
|
|
26
|
+
assigning roles, a set of RESIDENT subagents permanently collaborate: they message
|
|
27
|
+
each other, hold meetings, decide all task allocation themselves, persist their own
|
|
28
|
+
progress / proposition / method / sub-problem libraries, and verify objects ONLY by
|
|
29
|
+
unanimous consensus (else they stay as unverified with a probability). Anything is
|
|
30
|
+
verified only when ALL residents agree true or false.
|
|
31
|
+
|
|
32
|
+
Data lives under {{cwd}}/VibeMath/Projects/<project>/:
|
|
33
|
+
Problems/ (original problem card), Progress/<resident>/ (each resident's progress),
|
|
34
|
+
Propos/<resident>/ (each resident's propositions), Methods/<resident>/ (theories/tools),
|
|
35
|
+
Subproblems/<resident>/, Shared/ (meeting transcripts / task board / deadlines / debates),
|
|
36
|
+
Verified/ (read-only, ONLY after unanimous consensus), State/ (framework-private),
|
|
37
|
+
Reliable/ (references), Notes/.
|
|
38
|
+
|
|
39
|
+
Main controls:
|
|
40
|
+
- vibe_v4_start {problem, residentCount?, seedDirections?} — spawn residents, brainstorm, begin.
|
|
41
|
+
- vibe_v4_resume — resume a persisted run.
|
|
42
|
+
- vibe_v4_pause / vibe_v4_abort / vibe_v4_status / vibe_v4_report.
|
|
43
|
+
- vibe_v4_message {to|all, content} — inject a message to a resident (human/assistant intervention).
|
|
44
|
+
- vibe_v4_meeting {agenda} — force a meeting.
|
|
45
|
+
- vibe_v4_add_member {direction?} / vibe_v4_remove_member {id} — add / close a resident.
|
|
46
|
+
- vibe_v4_list_members — list residents.
|
|
47
|
+
- vibe_v4_set {compactAfterRounds, compactThreshold, residentCount, maxParallel, activityTimeoutMs}.
|
|
48
|
+
A /v4 slash command mirrors the main controls.
|
|
49
|
+
|
|
50
|
+
TRUST RULE: only Verified/ (and Propos/ entries marked 已验证·真/假) are absolutely
|
|
51
|
+
trustworthy; everything else — unverified resident claims, Progress/, Method claims —
|
|
52
|
+
is experiential reference. A proposition / method / theory only reaches Verified/ when
|
|
53
|
+
ALL residents unanimously agree true (or all agree false); otherwise it stays in its
|
|
54
|
+
library with a probability estimate.
|
|
55
|
+
|
|
56
|
+
When the user asks about progress, call vibe_v4_report and summarize in plain language.
|
|
57
|
+
|
|
58
|
+
# ── agent-instructions ──────────────────────────────────────────────────────
|
|
59
|
+
|
|
60
|
+
- id: agent-instructions
|
|
61
|
+
name: '@deepseek-ai/dsh-agent-instructions'
|
|
62
|
+
config:
|
|
63
|
+
maxBytes: 65536
|
|
64
|
+
|
|
65
|
+
# ── shell ───────────────────────────────────────────────────────────────────
|
|
66
|
+
|
|
67
|
+
- id: tool-bash
|
|
68
|
+
name: '@deepseek-ai/dsh-tool-bash'
|
|
69
|
+
disabled: !!js process.platform === 'win32'
|
|
70
|
+
|
|
71
|
+
- id: tool-pwsh
|
|
72
|
+
name: '@deepseek-ai/dsh-tool-pwsh'
|
|
73
|
+
disabled: !!js process.platform !== 'win32'
|
|
74
|
+
|
|
75
|
+
# ── filesystem ──────────────────────────────────────────────────────────────
|
|
76
|
+
|
|
77
|
+
- id: tool-fs
|
|
78
|
+
name: '@deepseek-ai/dsh-tool-fs'
|
|
79
|
+
|
|
80
|
+
- id: tool-fs-search
|
|
81
|
+
name: '@deepseek-ai/dsh-tool-fs-search'
|
|
82
|
+
config:
|
|
83
|
+
sampleOverCapGlobResults: false
|
|
84
|
+
|
|
85
|
+
# ── background jobs ────────────────────────────────────────────────────────
|
|
86
|
+
|
|
87
|
+
- id: tool-jobs
|
|
88
|
+
name: '@deepseek-ai/dsh-tool-jobs'
|
|
89
|
+
|
|
90
|
+
# ── skills ──────────────────────────────────────────────────────────────────
|
|
91
|
+
|
|
92
|
+
- id: skill-filesystem
|
|
93
|
+
name: '@deepseek-ai/dsh-skill-filesystem'
|
|
94
|
+
|
|
95
|
+
- id: tool-skill
|
|
96
|
+
name: '@deepseek-ai/dsh-tool-skill'
|
|
97
|
+
|
|
98
|
+
# ── goals ───────────────────────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
- id: tool-goal
|
|
101
|
+
name: '@deepseek-ai/dsh-tool-goal'
|
|
102
|
+
|
|
103
|
+
# ── plan mode ───────────────────────────────────────────────────────────────
|
|
104
|
+
|
|
105
|
+
- id: planning
|
|
106
|
+
name: cordis:group
|
|
107
|
+
group: true
|
|
108
|
+
isolate:
|
|
109
|
+
planMode: true
|
|
110
|
+
config:
|
|
111
|
+
- id: plan-mode
|
|
112
|
+
name: '@deepseek-ai/dsh-plan-mode'
|
|
113
|
+
config:
|
|
114
|
+
section: |
|
|
115
|
+
You are in plan mode. Stay in plan mode until exit_plan_mode succeeds or the user switches the session mode. Imperative language to implement changes means plan the implementation, not execute it. A user's conversational agreement — including an answer confirming something you asked — approves nothing and does not end plan mode; fold the confirmed decision into the plan and submit it through exit_plan_mode.
|
|
116
|
+
|
|
117
|
+
Explore first. Use non-mutating reads, searches, static analysis, and checks to ground the plan in the actual repository. Do not edit or write files, change configuration, run formatters or code generation that rewrites tracked files, commit, or otherwise carry out the plan. Prefer existing functions and patterns over new machinery.
|
|
118
|
+
|
|
119
|
+
The tool catalog stays the same across modes for request-cache stability. These plan-mode rules override any later tool description or guidance that suggests using mutation tools; those tools remain listed to keep the tool catalog unchanged. Do not use todo_write to track this planning phase: it tracks implementation after an approved plan, while the plan itself belongs in exit_plan_mode.
|
|
120
|
+
|
|
121
|
+
Resolve discoverable facts by inspection. Use ask_user_question only for user-owned choices or material ambiguity that inspection cannot answer. Do not ask the user where code lives or how current behavior works when you can find out.
|
|
122
|
+
|
|
123
|
+
Make the plan decision-complete: state the goal and success criteria; group implementation changes by subsystem; identify public API, schema, and data-flow changes; cover edge cases, failure modes, tests, acceptance criteria, and explicit assumptions. Keep it concise enough to review but detailed enough that another engineer can implement it without making design decisions.
|
|
124
|
+
|
|
125
|
+
When ready, call exit_plan_mode with the complete plan markdown, starting with a # title. Make exit_plan_mode the only and final tool call in that assistant response: it presents the plan for approval, and implementation begins only in a later step after approval. Do not paste the final plan as a plain reply or ask "should I proceed?" through prose or ask_user_question. If review rejects it, incorporate the feedback and present again. If the review channel is unavailable or aborted, stay in plan mode and ask the user to switch modes manually; do not proceed with implementation.
|
|
126
|
+
|
|
127
|
+
# ── compaction ──────────────────────────────────────────────────────────────
|
|
128
|
+
|
|
129
|
+
- id: compaction
|
|
130
|
+
name: cordis:group
|
|
131
|
+
group: true
|
|
132
|
+
isolate:
|
|
133
|
+
compaction: true
|
|
134
|
+
toolResultPruner: true
|
|
135
|
+
config:
|
|
136
|
+
- id: compaction-basic
|
|
137
|
+
name: '@deepseek-ai/dsh-compaction-basic'
|
|
138
|
+
|
|
139
|
+
- id: command-compact
|
|
140
|
+
name: '@deepseek-ai/dsh-command-compact'
|
|
141
|
+
|
|
142
|
+
- id: tool-result-pruner
|
|
143
|
+
name: '@deepseek-ai/dsh-compaction-tool-result-pruner'
|
|
144
|
+
config:
|
|
145
|
+
thresholdChars: 8192
|
|
146
|
+
headChars: 4096
|
|
147
|
+
tailChars: 1024
|
|
148
|
+
|
|
149
|
+
# ── delegation and workflows ────────────────────────────────────────────────
|
|
150
|
+
|
|
151
|
+
- id: delegation
|
|
152
|
+
name: cordis:group
|
|
153
|
+
group: true
|
|
154
|
+
isolate:
|
|
155
|
+
workflowEngine: true
|
|
156
|
+
config:
|
|
157
|
+
- id: tool-subagent-control
|
|
158
|
+
name: '@deepseek-ai/dsh-tool-subagent-control'
|
|
159
|
+
|
|
160
|
+
- id: tool-subagent-list-agents
|
|
161
|
+
name: '@deepseek-ai/dsh-tool-subagent-control/list-agents'
|
|
162
|
+
|
|
163
|
+
- id: tool-subagent
|
|
164
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
165
|
+
config:
|
|
166
|
+
provider: spawn
|
|
167
|
+
toolName: subagent
|
|
168
|
+
backgroundMode: continuable
|
|
169
|
+
|
|
170
|
+
- id: tool-subagent-fork
|
|
171
|
+
name: '@deepseek-ai/dsh-tool-subagent'
|
|
172
|
+
config:
|
|
173
|
+
provider: fork
|
|
174
|
+
toolName: subagent_fork
|
|
175
|
+
backgroundMode: continuable
|
|
176
|
+
|
|
177
|
+
- id: workflow-worker-thread
|
|
178
|
+
name: '@deepseek-ai/dsh-workflow-worker-thread'
|
|
179
|
+
config:
|
|
180
|
+
provider: spawn
|
|
181
|
+
|
|
182
|
+
- id: tool-workflow
|
|
183
|
+
name: '@deepseek-ai/dsh-tool-workflow'
|
|
184
|
+
|
|
185
|
+
- id: tool-ralph
|
|
186
|
+
name: '@deepseek-ai/dsh-tool-ralph'
|
|
187
|
+
config:
|
|
188
|
+
subagentProvider: spawn
|
|
189
|
+
maxRounds: 64
|
|
190
|
+
|
|
191
|
+
# ── remaining model-facing rows ─────────────────────────────────────────────
|
|
192
|
+
|
|
193
|
+
- id: tool-ask-user
|
|
194
|
+
name: '@deepseek-ai/dsh-tool-ask-user'
|
|
195
|
+
|
|
196
|
+
- id: tool-todo
|
|
197
|
+
name: '@deepseek-ai/dsh-tool-todo'
|
|
198
|
+
config:
|
|
199
|
+
allowParallelInProgress: true
|
|
200
|
+
|
|
201
|
+
- id: tool-web
|
|
202
|
+
name: '@deepseek-ai/dsh-tool-web'
|
|
203
|
+
config:
|
|
204
|
+
fetch: false
|
|
205
|
+
searchTimeoutMs: 60000
|
|
206
|
+
|
|
207
|
+
# ── Vibe Math V4 ────────────────────────────────────────────────────────────
|
|
208
|
+
|
|
209
|
+
# THE FOURTH-GENERATION framework: a preset-local plugin (./vibe-math-v4.js)
|
|
210
|
+
# that registers the vibe_v4_* tools + a /v4 slash command, and facilitates a
|
|
211
|
+
# persistent self-organizing band of resident subagents (message bus / meetings /
|
|
212
|
+
# per-resident artifact libraries / unanimous-consensus verification / context
|
|
213
|
+
# compaction / resume / human intervention). It consumes HOST
|
|
214
|
+
# subagents/agents/fs/tools/commands services and provides nothing, so it sits
|
|
215
|
+
# loose (no isolate realm).
|
|
216
|
+
- id: vibe-math-v4
|
|
217
|
+
name: './vibe-math-v4.js'
|
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
// Vibe Math V4 — persistent self-organizing collaborative research framework.
|
|
2
|
+
// FACILITATOR (message bus / meetings / per-resident artifact libraries /
|
|
3
|
+
// unanimous-consensus verification / context compaction proxy / resume / human
|
|
4
|
+
// intervention). It NEVER assigns tasks: residents message & meet and decide all
|
|
5
|
+
// task allocation among themselves. Consumes HOST subagents/agents/fs/tools/commands.
|
|
6
|
+
export function apply(ctx) {
|
|
7
|
+
const subagents = ctx.subagents
|
|
8
|
+
const agents = ctx.agents
|
|
9
|
+
const fs = ctx.fs
|
|
10
|
+
const tools = ctx.tools
|
|
11
|
+
const commands = ctx.commands
|
|
12
|
+
const subprocess = ctx.get('subprocess')
|
|
13
|
+
const sandboxPolicy = ctx.get('sandboxPolicy')
|
|
14
|
+
|
|
15
|
+
const sessions = new Map() // rootAgentId -> Session
|
|
16
|
+
const childOwner = new Map() // childId -> rootAgentId
|
|
17
|
+
const fileOwner = {} // process-level write lock
|
|
18
|
+
const processEpoch = String(Date.now()) + '-' + Math.random().toString(36).slice(2, 8)
|
|
19
|
+
|
|
20
|
+
function sessionIdOf(agent){ try { return (agent&&agent.id)?String(agent.id):undefined } catch(e){ return undefined } }
|
|
21
|
+
function rootOf(agent){ try { let cur=agent; const seen=new Set(); while(cur){ const id=cur.id; if(seen.has(id)) return cur; seen.add(id); const p=(cur.session&&cur.session.header)?cur.session.header.parentSession:undefined; if(p===undefined) return cur; const par=agents.get(p); if(!par) return cur; cur=par } } catch(e){} return agent }
|
|
22
|
+
function getSession(agent){ const root=rootOf(agent); const sid=sessionIdOf(root); if(sid===undefined) return undefined; let s=sessions.get(sid); if(!s){ s=makeSession(root,sid); sessions.set(sid,s) } return s }
|
|
23
|
+
|
|
24
|
+
function makeSession(rootAgent, sessionId) {
|
|
25
|
+
let currentProject = 'default'
|
|
26
|
+
const DEFAULT_PARAMS = {
|
|
27
|
+
residentCount: 4, compactThreshold: 66, compactAfterRounds: 8,
|
|
28
|
+
maxParallel: 3, activityTimeoutMs: 120000, verdictMaxRounds: 3,
|
|
29
|
+
provider: '', model: '', residentPersona: '',
|
|
30
|
+
}
|
|
31
|
+
let params = Object.assign({}, DEFAULT_PARAMS)
|
|
32
|
+
let running = false, autoDone = false, phase = 'idle'
|
|
33
|
+
let residents = new Map(), mailboxes = new Map(), taskboard = [], decisions = []
|
|
34
|
+
let meetings = [], reports = [], activityLog = []
|
|
35
|
+
let problemText = '', problemId = 'problem', runId = 'run-' + shortId()
|
|
36
|
+
let meetingState = null, verifyState = null, pendingVerify = null
|
|
37
|
+
let busy = new Set(), wakeKind = new Map(), currentResident = ''
|
|
38
|
+
let lastActivityAt = now()
|
|
39
|
+
const activityLogCap = 200
|
|
40
|
+
|
|
41
|
+
// ---- utils ----
|
|
42
|
+
function now(){ return Date.now() }
|
|
43
|
+
function uuid(){ const h='0123456789abcdef'; let s=''; for(let i=0;i<36;i++){ if(i===8||i===13||i===18||i===23) s+='-'; else s+=h[Math.floor(Math.random()*16)] } return s }
|
|
44
|
+
function shortId(){ const h='0123456789abcdef'; let s=''; for(let i=0;i<8;i++) s+=h[Math.floor(Math.random()*16)]; return s }
|
|
45
|
+
function clamp01(v){ const n=Number(v); if(!Number.isFinite(n)) return 0.5; return Math.max(0,Math.min(1,n)) }
|
|
46
|
+
function fmtTime(ts){ try { return new Date(ts||now()).toISOString().replace('T',' ').slice(0,19) } catch(e){ return String(ts||'') } }
|
|
47
|
+
function cl(x){ return clamp01(Number(x)) }
|
|
48
|
+
function textBlock(t){ return { type:'text', text:String(t) } }
|
|
49
|
+
function blocksToText(b){ if(!b) return ''; let out=''; for(const x of b){ if(x&&x.type==='text'&&typeof x.text==='string') out+=x.text+'\n' } return out.trim() }
|
|
50
|
+
function logActivity(event,detail){ activityLog.push({at:now(),event,detail:String(detail||'')}); if(activityLog.length>activityLogCap) activityLog.shift() }
|
|
51
|
+
function logDecision(kind,detail){ decisions.push({at:now(),kind,detail:String(detail||'')}) }
|
|
52
|
+
function pickProvider(){ try { const n=subagents.list?subagents.list():[]; if(n.indexOf('spawn')!==-1) return 'spawn'; if(n.indexOf('fork')!==-1) return 'fork' } catch(e){} return 'spawn' }
|
|
53
|
+
function makeSignal(ms){ return AbortSignal.timeout(ms||30000) }
|
|
54
|
+
function workspaceRoot(){ try { if(rootAgent&&rootAgent.session&&rootAgent.session.header&&rootAgent.session.header.cwd) return rootAgent.session.header.cwd } catch(e){} if(sandboxPolicy&&sandboxPolicy.workspaceRoot) return sandboxPolicy.workspaceRoot; return '.' }
|
|
55
|
+
function vibeRoot(){ return (workspaceRoot()+'/VibeMath').replace(/\\/g,'/') }
|
|
56
|
+
function frameworkRoot(){ return vibeRoot()+'/Projects/'+currentProject }
|
|
57
|
+
function slugify(s){ const t=String(s==null?'':s).trim().toLowerCase().replace(/[^a-z0-9_\-\u4e00-\u9fa5]+/g,'-').replace(/^-+|-+$/g,''); return t||'project' }
|
|
58
|
+
function getPolicy(){ try { if(sandboxPolicy&&rootAgent&&rootAgent.session) return sandboxPolicy.resolve({session:rootAgent.session}) } catch(e){} try { if(sandboxPolicy) return sandboxPolicy.resolve({}) } catch(e){} return undefined }
|
|
59
|
+
function psQuote(p){ return "'"+String(p).replace(/'/g,"''")+"'" }
|
|
60
|
+
async function runShell(script,cwd){ if(subprocess===undefined) return {ok:false,error:'no-subprocess'}; try { const h=subprocess.spawn({argv:['powershell','-NoProfile','-NonInteractive','-Command',script],cwd:cwd||workspaceRoot(),stdio:{stdin:'ignore',stdout:'inherit',stderr:'inherit'},graceMs:20000}); const o=await h.done; return {ok:o.exitCode===0,exitCode:o.exitCode} } catch(e){ return {ok:false,error:String((e&&e.message)||e)} } }
|
|
61
|
+
async function fsTarget(rel){ return await fs.resolve(rel,{cwd:frameworkRoot()}) }
|
|
62
|
+
async function readText(rel){ try { const t=await fsTarget(rel); if(await fs.stat(t)===undefined) return undefined; return await fs.readText(t) } catch(e){ return undefined } }
|
|
63
|
+
async function writeText(rel,content){ try { const t=await fsTarget(rel); await fs.writeText(t,content,undefined,undefined,getPolicy()); return true } catch(e){ return false } }
|
|
64
|
+
async function writeJson(rel,obj){ return await writeText(rel,JSON.stringify(obj,null,2)) }
|
|
65
|
+
async function readJson(rel){ const t=await readText(rel); if(t===undefined||t==='') return undefined; try { return JSON.parse(t) } catch(e){ return undefined } }
|
|
66
|
+
async function ensureDirs(){ const base=frameworkRoot(); const dirs=['Problems','Progress','Propos','Methods','Subproblems','Shared/meetings','Shared/debates','Verified/命题','Verified/问题','Reliable','Notes','State']; return await runShell('New-Item -Force -ItemType Directory -Path '+[vibeRoot()+'/Projects'].concat(dirs.map(d=>base+'/'+d)).map(psQuote).join(',')+' | Out-Null') }
|
|
67
|
+
async function readTextAbs(path){ try { const t=await fs.resolve(path); const s=await fs.stat(t); if(s===undefined) return undefined; return await fs.readText(t) } catch(e){ return undefined } }
|
|
68
|
+
async function writeTextAbs(path,content){ try { const t=await fs.resolve(path); await fs.writeText(t,content,undefined,undefined,getPolicy()); return true } catch(e){ return false } }
|
|
69
|
+
async function readCurrentProject(){ try { const t=await readTextAbs(vibeRoot()+'/.current'); if(t) return String(t).trim() } catch(e){} return currentProject }
|
|
70
|
+
async function writeCurrentProject(){ try { await writeTextAbs(vibeRoot()+'/.current', currentProject) } catch(e){} }
|
|
71
|
+
function tryJson(s){ try { return JSON.parse(s) } catch(e){ return undefined } }
|
|
72
|
+
function parseReply(text){
|
|
73
|
+
let obj; const fence=/```(?:json)?[ \t]*([\s\S]*?)```/gi; let m
|
|
74
|
+
while((m=fence.exec(text))!==null){ const o=tryJson(m[1].trim()); if(o&&typeof o==='object'&&!Array.isArray(o)) obj=o }
|
|
75
|
+
if(!obj){ const w=tryJson(text.trim()); if(w&&typeof w==='object'&&!Array.isArray(w)) obj=w }
|
|
76
|
+
return obj||{}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---- persistence ----
|
|
80
|
+
async function saveAll(){
|
|
81
|
+
await writeJson('State/residents.json', Object.fromEntries(residents))
|
|
82
|
+
await writeJson('State/mailboxes.json', Object.fromEntries(mailboxes))
|
|
83
|
+
await writeJson('State/taskboard.json', taskboard)
|
|
84
|
+
await writeJson('State/decisions.json', decisions)
|
|
85
|
+
await writeJson('State/session.json', {running,autoDone,phase,problemId,problemText,runId,meetings,reports,lastActivityAt,activityLog})
|
|
86
|
+
}
|
|
87
|
+
async function loadAll(){
|
|
88
|
+
const s=await readJson('State/session.json'); if(s){ running=!!s.running; autoDone=!!s.autoDone; phase=s.phase||'idle'; problemId=s.problemId||problemId; problemText=s.problemText||problemText; runId=s.runId||runId; meetings=s.meetings||[]; reports=s.reports||[]; lastActivityAt=s.lastActivityAt||now(); activityLog=s.activityLog||activityLog }
|
|
89
|
+
const rm=await readJson('State/residents.json'); if(rm&&typeof rm==='object') residents=new Map(Object.entries(rm))
|
|
90
|
+
const mb=await readJson('State/mailboxes.json'); if(mb&&typeof mb==='object') mailboxes=new Map(Object.entries(mb))
|
|
91
|
+
const tb=await readJson('State/taskboard.json'); if(Array.isArray(tb)) taskboard=tb
|
|
92
|
+
const dc=await readJson('State/decisions.json'); if(Array.isArray(dc)) decisions=dc
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// ---- resident prompts ----
|
|
96
|
+
function banner(){ const o=[]; for(const [id,r] of residents) o.push('- '+id+'「'+(r.direction||'(未定)')+'」'+r.status+'·轮'+r.rounds); return o.join('\n') }
|
|
97
|
+
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' }
|
|
98
|
+
function brainstormPrompt(r){
|
|
99
|
+
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
100
|
+
+'You are resident researcher '+r.rId+' (of '+params.residentCount+'), collaborating on:\n'+problemText
|
|
101
|
+
+(r.direction?('\n\nAssigned direction (you may refine it):\n'+r.direction):'')+'\n\n'
|
|
102
|
+
+'This is your FIRST, independent thinking round. Independently brainstorm: your insight / solution direction / sub-problems / plausible lemmas / rough plan. You do NOT see the others yet.\n'
|
|
103
|
+
+'Rules:\n- Only facts already in Verified/ are established; everything else is your own working (experiential), clearly mark conjecture vs known.\n'
|
|
104
|
+
+'- Record valuable artifacts to YOUR library via vibe_v4_publish_progress / vibe_v4_record_proposition / vibe_v4_record_method / vibe_v4_record_subproblem; each must carry 价值程度 / 动机用途计划 / 自身概率估计.\n'
|
|
105
|
+
+'Reply with ONLY a JSON object in a ```json fence (no prose outside):\n'
|
|
106
|
+
+'{"summary":"<your insight, one tight paragraph>","solved":false}'
|
|
107
|
+
}
|
|
108
|
+
async function normalPrompt(r){
|
|
109
|
+
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
110
|
+
+'You are resident researcher '+r.rId+' collaborating with '+Math.max(0,residents.size-1)+' other resident(s) on:\n'+problemText+'\n\nResidents:\n'+banner()+'\n\n'
|
|
111
|
+
+'This is your round (#'+r.rounds+'). You decide what to do — there is NO external assignment. Typical actions:\n'
|
|
112
|
+
+'- advance your direction; verify your own claims; record valuable artifacts to YOUR library (vibe_v4_publish_progress / record_proposition / record_method / record_subproblem), each with 价值程度 / 动机用途计划 / 自身概率估计;\n'
|
|
113
|
+
+'- message a specific resident (vibe_v4_send_message) or broadcast;\n'
|
|
114
|
+
+'- call a meeting (vibe_v4_meeting) to coordinate / allocate tasks / propose a verification;\n'
|
|
115
|
+
+'- propose an object for unanimous verification (set propose_verify in your reply).\n'
|
|
116
|
+
+'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'
|
|
117
|
+
+'Rules:\n- Only Verified/ is established. Verification requires ALL residents unanimous; you trust only unanimous results.\n'
|
|
118
|
+
+'- If the ORIGINAL problem is solved, set solved=true (we stop only when ALL residents agree).\n'
|
|
119
|
+
+'New items:\n'+ (await inboxText(r.rId))
|
|
120
|
+
+'\nReply with ONLY a JSON object in a ```json fence (no prose outside):\n'
|
|
121
|
+
+'{"summary":"<what you did this round, 1-3 sentences>","solved":false,"propose_verify":"<a target id like p-xxx / m-xxx / s-xxx, or null>"}'
|
|
122
|
+
}
|
|
123
|
+
function meetingPrompt(r, st){
|
|
124
|
+
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
125
|
+
+'You are resident '+r.rId+'. A meeting is in progress (agenda: '+st.agenda+').'
|
|
126
|
+
+(st.type==='verify'?('\nThe group is verifying object: '+st.targetId+'. Give your independent verdict.'):'')
|
|
127
|
+
+'\nGive your input. If the agenda is about whether the original problem is solved, set voteSolved.\n'
|
|
128
|
+
+'Reply with ONLY a JSON object (```json fence):\n'
|
|
129
|
+
+'{"input":"<your contribution>","voteSolved":true,"propose_verify":"<id or null>"}'
|
|
130
|
+
}
|
|
131
|
+
function verifyPrompt(r, vs){
|
|
132
|
+
const others=Object.entries(vs.verdicts).map(([k,v])=>'- '+k+': '+v.verdict+' ('+v.confidence+') '+v.reason).join('\n')
|
|
133
|
+
return (params.residentPersona?params.residentPersona+'\n':'')
|
|
134
|
+
+'You are resident '+r.rId+'. The group is verifying object '+vs.targetId+' ('+vs.targetType+'). '
|
|
135
|
+
+'It may be TRUE only if ALL residents agree true (FALSE only if ALL agree false). Give your honest independent verdict'
|
|
136
|
+
+(vs.stage==='debate'?' after considering the others:':'')+'.\n'
|
|
137
|
+
+(vs.stage==='debate'?('Others so far:\n'+others):'')
|
|
138
|
+
+'\nReply with ONLY a JSON object (```json fence):\n'
|
|
139
|
+
+'{"vote":{"verdict":"TRUE","confidence":0.8,"reason":"<your logic>"}}'
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// ---- resident lifecycle ----
|
|
143
|
+
function newResident(dir){ const rId='r-'+(residents.size+1); return {rId,childId:'',direction:dir||'',status:'brainstorm',rounds:0,roundsSinceCompact:0,lastActiveAt:now(),insight:''} }
|
|
144
|
+
async function spawnResident(r){
|
|
145
|
+
const started=await subagents.startContinuable({provider:pickProvider(),label:r.rId,request:{prompt:[textBlock(brainstormPrompt(r))],parent:rootAgent,agentOptions:{}},signal:makeSignal(60000)})
|
|
146
|
+
r.childId=started.childId; r.status='brainstorm'; r.lastActiveAt=now()
|
|
147
|
+
childOwner.set(started.childId,sessionId); busy.add(r.rId); wakeKind.set(r.rId,'normal'); currentResident=r.rId
|
|
148
|
+
residents.set(r.rId,r); await saveAll(); logActivity('spawn',r.rId+' ('+(r.direction||'brainstorm')+')')
|
|
149
|
+
}
|
|
150
|
+
async function wakeResident(r, promptText, kind){
|
|
151
|
+
if(!r.childId) return false
|
|
152
|
+
busy.add(r.rId); wakeKind.set(r.rId,kind||'normal'); currentResident=r.rId
|
|
153
|
+
r.lastActiveAt=now(); r.rounds+=1; r.roundsSinceCompact+=1
|
|
154
|
+
try { await subagents.followup(rootAgent,r.childId,[textBlock(promptText)],{source:{kind:'user'},signal:makeSignal(60000)}); return true }
|
|
155
|
+
catch(e){ console.error('vibe-v4 wake '+r.rId+' failed: '+String((e&&e.message)||e)); busy.delete(r.rId); return false }
|
|
156
|
+
}
|
|
157
|
+
function byChild(childId){ for(const [,r] of residents){ if(r.childId===childId) return r } return undefined }
|
|
158
|
+
|
|
159
|
+
// ---- artifact writers (resident-facing) ----
|
|
160
|
+
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} }
|
|
161
|
+
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); return {ok:true,id,file:'Propos/'+rId+'/'+id+'.md'} }
|
|
162
|
+
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); return {ok:true,id,file:'Methods/'+rId+'/'+id+'.md'} }
|
|
163
|
+
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); return {ok:true,id,file:'Subproblems/'+rId+'/'+id+'.md'} }
|
|
164
|
+
function listResidents(){ return Array.from(residents.values()).map(r=>({id:r.rId,direction:r.direction,status:r.status,rounds:r.rounds,insight:r.insight?r.insight.slice(0,80):''})) }
|
|
165
|
+
|
|
166
|
+
// ---- messaging ----
|
|
167
|
+
async function postMessage(from,to,content){
|
|
168
|
+
const r=residents.get(to); if(!r) return {ok:false,message:'no such resident'}
|
|
169
|
+
if(!busy.has(to)){
|
|
170
|
+
currentResident=r.rId
|
|
171
|
+
await wakeResident(r, (await normalPrompt(r))+'\n\n[NEW MESSAGE from '+from+']\n'+content,'normal')
|
|
172
|
+
await saveAll(); logActivity('message',from+'→'+to); return {ok:true}
|
|
173
|
+
}
|
|
174
|
+
const mb=mailboxes.get(to)||[]; mb.push({from,at:now(),content}); mailboxes.set(to,mb); await saveAll(); logActivity('message',from+'→'+to+' (queued)'); return {ok:true}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// ---- meeting ----
|
|
178
|
+
async function startMeeting(agenda,type,targetId){
|
|
179
|
+
if(meetingState) return {ok:false,message:'meeting already in progress'}
|
|
180
|
+
meetingState={id:'mt-'+shortId(),agenda,type:type||'general',targetId:targetId||null,round:0,asked:[],inputs:{},transcript:[]}
|
|
181
|
+
logActivity('meeting','start: '+agenda); await saveAll(); await scheduleNext(); return {ok:true,id:meetingState.id}
|
|
182
|
+
}
|
|
183
|
+
async function continueMeetingRound(){
|
|
184
|
+
if(!meetingState) return
|
|
185
|
+
const ids=Array.from(residents.keys()); const allAsked=ids.every(id=>meetingState.asked.indexOf(id)!==-1)
|
|
186
|
+
if(allAsked){ await finalizeMeeting(); return }
|
|
187
|
+
// only wake IDLE residents (never double-wake a busy one; in-flight ones re-trigger this on end)
|
|
188
|
+
const id=ids.find(x=>meetingState.asked.indexOf(x)===-1 && !busy.has(x)); if(!id) return
|
|
189
|
+
meetingState.asked.push(id); const r=residents.get(id)
|
|
190
|
+
await wakeResident(r, meetingPrompt(r,meetingState), 'meeting'); await saveAll()
|
|
191
|
+
}
|
|
192
|
+
async function finalizeMeeting(){
|
|
193
|
+
const st=meetingState
|
|
194
|
+
const lines=['# 会议 '+st.id+'|'+fmtTime(),'','**议程**:'+st.agenda,'']
|
|
195
|
+
for(const [id,iv] of Object.entries(st.inputs)){ lines.push('### '+id); lines.push(iv.input||''); lines.push('') }
|
|
196
|
+
await writeText('Shared/meetings/'+st.id+'.md', lines.join('\n'))
|
|
197
|
+
meetings.push({id:st.id,agenda:st.agenda,at:now(),inputs:st.inputs})
|
|
198
|
+
logDecision('meeting',st.agenda)
|
|
199
|
+
const votes=Object.values(st.inputs).map(x=>x.voteSolved).filter(v=>typeof v==='boolean')
|
|
200
|
+
const allSolved=votes.length>0 && votes.every(v=>v===true)
|
|
201
|
+
logActivity('meeting', 'concluded'+(allSolved?' → ALL agree solved':''))
|
|
202
|
+
if(allSolved){ running=false; autoDone=true; phase='done'; logActivity('stop','all residents agree: problem solved'); await saveAll(); return }
|
|
203
|
+
meetingState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// ---- verification (unanimous) ----
|
|
207
|
+
async function beginVerify(pv){
|
|
208
|
+
pendingVerify=null
|
|
209
|
+
verifyState={targetId:pv.targetId,targetType:pv.targetType,stage:'independent',round:0,asked:[],verdicts:{},transcript:[]}
|
|
210
|
+
logActivity('verify','debate begin: '+pv.targetId+' ('+pv.targetType+')'); await saveAll(); await scheduleNext()
|
|
211
|
+
}
|
|
212
|
+
async function continueVerifyRound(){
|
|
213
|
+
if(!verifyState) return
|
|
214
|
+
const ids=Array.from(residents.keys()); const allAsked=ids.every(id=>verifyState.asked.indexOf(id)!==-1)
|
|
215
|
+
if(allAsked){ await finalizeVerify(); return }
|
|
216
|
+
// only wake IDLE residents (never double-wake; in-flight ones re-trigger this on end)
|
|
217
|
+
const id=ids.find(x=>verifyState.asked.indexOf(x)===-1 && !busy.has(x)); if(!id) return
|
|
218
|
+
verifyState.asked.push(id); const r=residents.get(id)
|
|
219
|
+
await wakeResident(r, verifyPrompt(r,verifyState), verifyState.stage==='independent'?'verif-ind':'verif-deb'); await saveAll()
|
|
220
|
+
}
|
|
221
|
+
async function finalizeVerify(){
|
|
222
|
+
const vs=verifyState; const vals=Object.values(vs.verdicts)
|
|
223
|
+
const allTrue=vals.length>0 && vals.every(x=>x.verdict==='TRUE')
|
|
224
|
+
const allFalse=vals.length>0 && vals.every(x=>x.verdict==='FALSE')
|
|
225
|
+
if(allTrue||allFalse){ await closeVerify(vs,allTrue); return }
|
|
226
|
+
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 }
|
|
227
|
+
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
|
|
228
|
+
await writeDebateDoc(vs,false,avg); logActivity('verify',vs.targetId+' NOT unanimous → kept unverified (avg '+avg.toFixed(2)+')')
|
|
229
|
+
verifyState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
|
|
230
|
+
}
|
|
231
|
+
async function closeVerify(vs,isTrue){
|
|
232
|
+
await writeDebateDoc(vs,true,isTrue?1:0)
|
|
233
|
+
const target=vs.targetId
|
|
234
|
+
await writeVerifiedCard(vs,isTrue)
|
|
235
|
+
await rewriteSource(target,isTrue)
|
|
236
|
+
logActivity('verify',target+' → Verified ('+(isTrue?'真':'假')+') by unanimous consensus')
|
|
237
|
+
verifyState=null; wakeKind.clear(); await saveAll(); await scheduleNext()
|
|
238
|
+
}
|
|
239
|
+
async function writeDebateDoc(vs,done,val){
|
|
240
|
+
const lines=['# 验证辩论|'+vs.targetId+'('+vs.targetType+')|'+fmtTime(),'',(done?('**结论**:'+(val===1?'全体一致为真':'全体一致为假')):('**未达成全体一致**,平均概率 '+val.toFixed(2))),'','## 各常驻意见']
|
|
241
|
+
for(const [k,v] of Object.entries(vs.verdicts)){ lines.push('### '+k+'|'+v.verdict+'|'+v.confidence); lines.push(v.reason||''); lines.push('') }
|
|
242
|
+
await writeText('Shared/debates/'+vs.targetId+'.md', lines.join('\n'))
|
|
243
|
+
}
|
|
244
|
+
async function writeVerifiedCard(vs,isTrue){
|
|
245
|
+
const dir= vs.targetType==='subproblem'?'问题':'命题'
|
|
246
|
+
const text='# 已验证|'+vs.targetId+'\n- ID: '+vs.targetId+'\n- 类型: '+(vs.targetType==='subproblem'?'问题':'命题')+'\n- 结论: '+(isTrue?'真':'假')+'\n- 概率: '+(isTrue?1:0)+'\n- 来源: 全体常驻一致\n## 陈述\n参见来源卡。\n'
|
|
247
|
+
await writeText('Verified/'+dir+'/'+vs.targetId+'.md', text)
|
|
248
|
+
}
|
|
249
|
+
async function rewriteSource(target,isTrue){
|
|
250
|
+
// find & update the source card status/prob; best effort across per-resident libs
|
|
251
|
+
let rel=null
|
|
252
|
+
for(const [rid] of residents){
|
|
253
|
+
for(const base of ['Propos','Methods','Subproblems']){
|
|
254
|
+
const cand=base+'/'+rid+'/'+target+'.md'; if((await readText(cand))!==undefined){ rel=cand; break }
|
|
255
|
+
}
|
|
256
|
+
if(rel) break
|
|
257
|
+
}
|
|
258
|
+
if(!rel) rel='Propos/'+target+'.md'
|
|
259
|
+
let text=(await readText(rel))||''
|
|
260
|
+
text=text.replace(/(^|\n)- 状态:.*/m,'$1'+(isTrue?'- 状态: 已验证·真':'- 状态: 已验证·假'))
|
|
261
|
+
.replace(/(^|\n)- 概率:.*/m,'$1'+(isTrue?'- 概率: 1':'- 概率: 0'))
|
|
262
|
+
await writeText(rel,text)
|
|
263
|
+
}
|
|
264
|
+
function guessTargetType(id){ if(/^p-/.test(id)) return 'proposition'; if(/^m-/.test(id)) return 'method'; if(/^s-/.test(id)) return 'subproblem'; return 'proposition' }
|
|
265
|
+
|
|
266
|
+
// ---- liveness / scheduling ----
|
|
267
|
+
async function scheduleNext(){
|
|
268
|
+
if(!running||autoDone) return
|
|
269
|
+
if(phase==='brainstorm'){ await maybeFinishBrainstorm(); return }
|
|
270
|
+
if(meetingState){ await continueMeetingRound(); return }
|
|
271
|
+
if(verifyState){ await continueVerifyRound(); return }
|
|
272
|
+
if(pendingVerify){ const pv=pendingVerify; await beginVerify(pv); return }
|
|
273
|
+
// mailbox delivery
|
|
274
|
+
const delivered=await deliverNextMailbox(); if(delivered) return
|
|
275
|
+
// fairness / coordination wake of the least-recently-active resident
|
|
276
|
+
let target=null, oldest=-1
|
|
277
|
+
for(const [,r] of residents){ if(busy.has(r.rId)) continue; const idle=now()-r.lastActiveAt; if(idle>oldest){ oldest=idle; target=r } }
|
|
278
|
+
if(target){ await wakeResident(target, await normalPrompt(target), 'normal'); await saveAll(); return }
|
|
279
|
+
}
|
|
280
|
+
async function maybeFinishBrainstorm(){
|
|
281
|
+
const pending=[]; for(const [,r] of residents){ if(r.status==='brainstorm' && !r.insight) pending.push(r.rId) }
|
|
282
|
+
if(pending.length===0){ phase='active'; logActivity('phase','active — residents now self-organize'); await saveBrainstormSummary(); await saveAll(); await scheduleNext() }
|
|
283
|
+
}
|
|
284
|
+
async function saveBrainstormSummary(){
|
|
285
|
+
const lines=['# 头脑风暴','']; for(const [,r] of residents){ if(r.insight){ lines.push('## '+r.rId+'「'+(r.direction||'')+'」'); lines.push(r.insight); lines.push('') } }
|
|
286
|
+
await writeText('Shared/meetings/brainstorm.md', lines.join('\n'))
|
|
287
|
+
}
|
|
288
|
+
async function deliverNextMailbox(){
|
|
289
|
+
for(const [to,msgs] of mailboxes){
|
|
290
|
+
if(msgs.length===0) continue
|
|
291
|
+
const m=msgs.shift(); const r=residents.get(to); if(!r){ continue }
|
|
292
|
+
if(!busy.has(to)){ currentResident=to; await wakeResident(r, (await normalPrompt(r))+'\n\n[MESSAGE from '+m.from+']\n'+m.content,'normal'); await saveAll(); return true }
|
|
293
|
+
msgs.push(m); return false
|
|
294
|
+
}
|
|
295
|
+
return false
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// ---- resident end handler ----
|
|
299
|
+
async function onResidentEnd(childId, info){
|
|
300
|
+
const r=byChild(childId); if(!r) return
|
|
301
|
+
busy.delete(r.rId)
|
|
302
|
+
const output=blocksToText(info&&info.lastAssistantMessage)
|
|
303
|
+
const parsed=parseReply(output)
|
|
304
|
+
const kind=wakeKind.get(r.rId)||'normal'
|
|
305
|
+
if(kind==='meeting' && meetingState){
|
|
306
|
+
meetingState.inputs[r.rId]={input:parsed.input||parsed.summary||'',voteSolved:typeof parsed.voteSolved==='boolean'?parsed.voteSolved:null,propose_verify:parsed.propose_verify||null}
|
|
307
|
+
if(parsed.propose_verify) pendingVerify={targetId:parsed.propose_verify,targetType:guessTargetType(parsed.propose_verify),proposer:r.rId,at:now()}
|
|
308
|
+
await saveAll(); await continueMeetingRound(); return
|
|
309
|
+
}
|
|
310
|
+
if((kind==='verif-ind'||kind==='verif-deb') && verifyState){
|
|
311
|
+
const v=(parsed&&parsed.vote)||{}
|
|
312
|
+
const verdict=String(v.verdict)==='TRUE'?'TRUE':String(v.verdict)==='FALSE'?'FALSE':'UNCERTAIN'
|
|
313
|
+
verifyState.verdicts[r.rId]={verdict,confidence:cl(v.confidence!=null?v.confidence:0.5),reason:String(v.reason||parsed.summary||'')}
|
|
314
|
+
await saveAll(); await continueVerifyRound(); return
|
|
315
|
+
}
|
|
316
|
+
// normal turn
|
|
317
|
+
if(r.status==='brainstorm'){ r.insight=parsed.summary||output; r.status='active' }
|
|
318
|
+
if(typeof parsed.solved==='boolean') reports.push({rId:r.rId,solved:parsed.solved,summary:parsed.summary||'',at:now()})
|
|
319
|
+
if(parsed.propose_verify) pendingVerify={targetId:parsed.propose_verify,targetType:guessTargetType(parsed.propose_verify),proposer:r.rId,at:now()}
|
|
320
|
+
// a resident may self-trigger a meeting (resident-driven coordination, closest to the philosophy)
|
|
321
|
+
if(parsed.propose_meeting && !meetingState){ await startMeeting(String(parsed.propose_meeting),'general',null); await saveAll(); return }
|
|
322
|
+
await saveAll(); await scheduleNext()
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// ---- controls ----
|
|
326
|
+
async function start({problem,residentCount,seedDirections}){
|
|
327
|
+
if(!problem) return {ok:false,message:'problem text required'}
|
|
328
|
+
currentProject=await readCurrentProject(); if(!currentProject||currentProject==='default'){ currentProject='default'; }
|
|
329
|
+
await ensureDirs()
|
|
330
|
+
problemText=String(problem); problemId=slugify(String(problem).slice(0,40))||'problem'
|
|
331
|
+
if(residentCount) params.residentCount=Number(residentCount)||4
|
|
332
|
+
running=true; autoDone=false; phase='brainstorm'
|
|
333
|
+
await writeText('Problems/'+problemId+'.md','# 问题|'+problemId+'\n- ID: '+problemId+'\n- 类型: 问题\n- 状态: 求解中\n- 优先级: 1\n- 依赖: []\n\n## 陈述\n'+problemText+'\n')
|
|
334
|
+
residents=new Map(); mailboxes=new Map(); taskboard=[]; decisions=[]; meetings=[]; reports=[]; verifyState=null; meetingState=null; pendingVerify=null
|
|
335
|
+
const dirs=Array.isArray(seedDirections)?seedDirections.slice(0,params.residentCount):[]
|
|
336
|
+
for(let i=0;i<params.residentCount;i++){ const r=newResident(dirs[i]||''); await spawnResident(r) }
|
|
337
|
+
await saveAll(); return {ok:true,message:'v4 started: '+params.residentCount+' resident(s) brainstorming',project:currentProject}
|
|
338
|
+
}
|
|
339
|
+
async function resume(){
|
|
340
|
+
currentProject=await readCurrentProject(); await ensureDirs(); await loadAll()
|
|
341
|
+
if(phase==='idle' && !running) return {ok:false,message:'nothing to resume'}
|
|
342
|
+
for(const [,r] of residents){ if(!r.childId){ await spawnResident(r) } }
|
|
343
|
+
if(!running){ running=true; autoDone=false; if(phase==='idle') phase='active' }
|
|
344
|
+
logActivity('resume','restarted'); await saveAll(); return {ok:true,message:'resumed',project:currentProject}
|
|
345
|
+
}
|
|
346
|
+
function status(){ return { ok:true, running, phase, autoDone, project:currentProject, residentCount:residents.size,
|
|
347
|
+
residents:listResidents(), busy:[...busy], taskboard:taskboard.length,
|
|
348
|
+
params:['residentCount','compactAfterRounds','compactThreshold','maxParallel','activityTimeoutMs'].map(k=>k+'='+params[k]).join(', ') } }
|
|
349
|
+
function report(){ return { ok:true, running, phase, autoDone, project:currentProject, problem:problemText,
|
|
350
|
+
residents:listResidents(), taskboard:taskboard.filter(t=>t.status!=='done'),
|
|
351
|
+
verify: verifyState?{target:verifyState.targetId,stage:verifyState.stage}:null, meetings:meetings.length,
|
|
352
|
+
recentActivity: activityLog.slice(-8) } }
|
|
353
|
+
async function addMember(direction){ const r=newResident(direction||''); await spawnResident(r); return {ok:true,id:r.rId,direction:r.direction} }
|
|
354
|
+
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} }
|
|
355
|
+
function setParams(upd){ for(const k of Object.keys(upd||{})){ if(k in params) params[k]=upd[k] } return {ok:true} }
|
|
356
|
+
function initAbort(){ 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){} } }; return {ok:true,message:'aborted'} }
|
|
357
|
+
function setPause(){ running=false; return {ok:true,message:'paused'} }
|
|
358
|
+
|
|
359
|
+
return {
|
|
360
|
+
sessionId, running:()=>running, autoDone:()=>autoDone, phase:()=>phase,
|
|
361
|
+
onResidentEnd, start, resume, status, report, addMember, removeMember, setParams,
|
|
362
|
+
setPause, initAbort, postMessage, startMeeting, saveAll,
|
|
363
|
+
currentResident:()=>currentResident,
|
|
364
|
+
useResident:(id)=>{ currentResident=id },
|
|
365
|
+
publishProgress, recordProposition, recordMethod, recordSubproblem, listResidents,
|
|
366
|
+
readProgress: async (rid)=>({text:(await readText('Progress/'+rid+'/progress.md'))||''}),
|
|
367
|
+
frameworkRoot:frameworkRoot, currentProject:()=>currentProject, problemText:()=>problemText,
|
|
368
|
+
residentCount:()=>residents.size,
|
|
369
|
+
busyCount:()=>busy.size,
|
|
370
|
+
}
|
|
371
|
+
} // end makeSession
|
|
372
|
+
|
|
373
|
+
// ================= apply-level registration (ONCE) =================
|
|
374
|
+
function objParams(props, required){ return { type:'object', properties:props, additionalProperties:false, required:required||[] } }
|
|
375
|
+
function registerTool(name, description, parameters, fn){
|
|
376
|
+
tools.register({ name, description, parameters,
|
|
377
|
+
output:{ schema:{ type:'string' }, render:(_a,v)=>[{type:'text',text:String(v)}] },
|
|
378
|
+
execute: async (args, exec)=>{
|
|
379
|
+
try { const s=getSession(exec&&exec.agent); if(!s) return JSON.stringify({ok:false,error:'no session'}); return JSON.stringify(await fn(s,args||{})) }
|
|
380
|
+
catch(e){ return JSON.stringify({ok:false,error:String((e&&e.message)||e)}) }
|
|
381
|
+
} })
|
|
382
|
+
}
|
|
383
|
+
// host/assistant-facing
|
|
384
|
+
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))
|
|
385
|
+
registerTool('vibe_v4_resume','Resume a persisted V4 run.',objParams({}),(s)=>s.resume())
|
|
386
|
+
registerTool('vibe_v4_pause','Pause V4.',objParams({}),(s)=>s.setPause())
|
|
387
|
+
registerTool('vibe_v4_abort','Abort V4 and interrupt residents.',objParams({}),(s)=>s.initAbort())
|
|
388
|
+
registerTool('vibe_v4_status','Show V4 status.',objParams({}),(s)=>s.status())
|
|
389
|
+
registerTool('vibe_v4_report','Return the V4 progress report.',objParams({}),(s)=>s.report())
|
|
390
|
+
registerTool('vibe_v4_message','Inject a message to a resident (or all).',objParams({to:{type:'string'},content:{type:'string'}},['to','content']),(s,a)=>{ const to=a.to||'all'; if(to==='all'){ return {ok:true,message:'broadcast: '+(a.content)} } return s.postMessage('facilitator',to,a.content) })
|
|
391
|
+
registerTool('vibe_v4_meeting','Start a meeting (coordinate / allocate / propose verification).',objParams({agenda:{type:'string'}},['agenda']),(s,a)=>s.startMeeting(a.agenda))
|
|
392
|
+
registerTool('vibe_v4_list_members','List residents.',objParams({}),(s)=>({ok:true,residents:s.listResidents()}))
|
|
393
|
+
registerTool('vibe_v4_add_member','Add a resident.',objParams({direction:{type:'string'}}),(s,a)=>s.addMember(a.direction))
|
|
394
|
+
registerTool('vibe_v4_remove_member','Close a resident.',objParams({id:{type:'string'}},['id']),(s,a)=>s.removeMember(a.id))
|
|
395
|
+
registerTool('vibe_v4_set','Set V4 parameters.',objParams({residentCount:{type:'integer'},compactAfterRounds:{type:'integer'},compactThreshold:{type:'integer'},maxParallel:{type:'integer'},activityTimeoutMs:{type:'integer'}}),(s,a)=>{ s.setParams(a); return {ok:true} })
|
|
396
|
+
// resident-facing tools: route to the CURRENT (last-woken) resident of the session
|
|
397
|
+
registerTool('vibe_v4_send_message','(resident) Send a message to another resident.',objParams({to:{type:'string'},content:{type:'string'}},['to','content']),(s,a)=>s.postMessage(s.currentResident(),a.to,a.content))
|
|
398
|
+
registerTool('vibe_v4_publish_progress','(resident) Append to your own progress markdown.',objParams({content:{type:'string'}},['content']),(s,a)=>s.publishProgress(s.currentResident(),a.content))
|
|
399
|
+
registerTool('vibe_v4_record_proposition','(resident) Record a proposition to your library.',objParams({id:{type:'string'},title:{type:'string'},statement:{type:'string'},prob:{type:'number'},value:{type:'number'},motivation:{type:'string'}}),(s,a)=>s.recordProposition(s.currentResident(),a))
|
|
400
|
+
registerTool('vibe_v4_record_method','(resident) Record a method/theory to your library.',objParams({id:{type:'string'},title:{type:'string'},type:{type:'string'},content:{type:'string'},notation:{type:'string'},value:{type:'number'},motivation:{type:'string'}}),(s,a)=>s.recordMethod(s.currentResident(),a))
|
|
401
|
+
registerTool('vibe_v4_record_subproblem','(resident) Record a sub-problem to your library.',objParams({id:{type:'string'},title:{type:'string'},statement:{type:'string'},value:{type:'number'},motivation:{type:'string'}}),(s,a)=>s.recordSubproblem(s.currentResident(),a))
|
|
402
|
+
registerTool('vibe_v4_read_progress','(resident) Read another resident\'s progress (read-only).',objParams({id:{type:'string'}},['id']),(s,a)=>({ok:true,text:(s.readProgress(a.id))}))
|
|
403
|
+
registerTool('vibe_v4_list_residents','(resident) List fellow residents.',objParams({}),(s)=>({ok:true,residents:s.listResidents()}))
|
|
404
|
+
registerTool('vibe_v4_claim_write','Reserved: shared-file write lock (framework-managed).',objParams({target:{type:'string'}},['target']),(s,a)=>({ok:true,key:a.target}))
|
|
405
|
+
registerTool('vibe_v4_release_write','Reserved: shared-file write lock release.',objParams({target:{type:'string'}},['target']),(s,a)=>({ok:true,key:a.target}))
|
|
406
|
+
|
|
407
|
+
commands.register({
|
|
408
|
+
name:'v4', description:'control the Vibe Math V4 framework',
|
|
409
|
+
input:{hint:'[start|resume|pause|abort|status|report|meeting|members|add|remove|set]'},
|
|
410
|
+
handler: async function(inv){
|
|
411
|
+
const s=getSession(inv&&inv.agent); if(!s) return {kind:'success',text:JSON.stringify({ok:false,error:'no session'})}
|
|
412
|
+
const line=String(inv&&inv.rawInput?inv.rawInput:'').trim(); const parts=line.split(/\s+/); const cmd=parts[0]||''; const rest=parts.slice(1)
|
|
413
|
+
let r
|
|
414
|
+
if(cmd==='start') r=await s.start({problem:rest.join(' ')})
|
|
415
|
+
else if(cmd==='resume') r=await s.resume()
|
|
416
|
+
else if(cmd==='pause') r=s.setPause()
|
|
417
|
+
else if(cmd==='abort') r=s.initAbort()
|
|
418
|
+
else if(cmd==='status') r=s.status()
|
|
419
|
+
else if(cmd==='report') r=s.report()
|
|
420
|
+
else if(cmd==='meeting') r=await s.startMeeting(rest.join(' '))
|
|
421
|
+
else if(cmd==='members') r={ok:true,residents:s.listResidents()}
|
|
422
|
+
else if(cmd==='add') r=await s.addMember(rest.join(' '))
|
|
423
|
+
else if(cmd==='remove') r=await s.removeMember(rest[0]||'')
|
|
424
|
+
else r={ok:false,usage:'start|resume|pause|abort|status|report|message|meeting|members|add|remove|set'}
|
|
425
|
+
return {kind:'success',text:JSON.stringify(r,null,2)}
|
|
426
|
+
},
|
|
427
|
+
})
|
|
428
|
+
|
|
429
|
+
ctx.on('subagent/end', function(info){
|
|
430
|
+
const sid=childOwner.get(info.id); const s=sid!==undefined?sessions.get(sid):undefined
|
|
431
|
+
if(s) s.onResidentEnd(info.id, info).catch(e=>console.error('vibe-v4 end: '+String((e&&e.stack)||e)))
|
|
432
|
+
})
|
|
433
|
+
}
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# Vibe Math V4 —— 常驻自组织合作研究框架(架构设计与实现方案)
|
|
2
|
+
|
|
3
|
+
> **一句话定位**:把 v3 的"中央规划器 + 确定性角色(explorer/solver/verifier/planner/method-keeper)"调度,升级为一组**持久化的常驻子代理**——它们之间**互相留言、集体开会**,自主决定接下来的一切任务(探索、尝试、验证、分工)。框架只做**媒介(消息总线/会议/任务板)、产物沉淀、共识验证、上下文管理、断点续跑**,**绝不分配任务**。像现实中的合作研究小组:人人有自己持续积累的笔记本与成果库,互相看、互相讨论、共同定论。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 0. 背景与动机
|
|
8
|
+
|
|
9
|
+
v3(以及 v1/v2)给人的观感:**每个代理太专攻、上下文被切得太零碎**——explorer 只管拆方向、solver 只管一轮、verifier 只管审查、planner 调度、method-keeper 沉淀;各自只见局部,缺少"一个研究者持续投入、与人碰撞"的整体感。解决的产物也散落在多个角色的产出里,缺乏一个人一贯的思考痕迹。
|
|
10
|
+
|
|
11
|
+
V4 的核心转变:**让"研究者"本身成为主体**——若干常驻子代理持续存在、各自持有方向与积累,它们的交流与决策就是整个系统的"调度"。系统不再"指挥"它们,而是**促成**它们交流、**记录**它们的成果、**只在它们一致同意时**定论。
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## 1. 与 v1/v2/v3 对比
|
|
16
|
+
|
|
17
|
+
| 维度 | v1(流水线) | v2(概率驱动) | v3(规划代理+角色) | **v4(常驻自组织)** |
|
|
18
|
+
|---|---|---|---|---|
|
|
19
|
+
| 调度 | 固定流水线状态机 | 代码启发式固定序 | 规划代理产 N 步计划 | **无中央调度**;任务由常驻互相通信/会议涌现 |
|
|
20
|
+
| 工作者 | 一次性子代理 | 一次性子代理 | 一次性子代理 | **常驻子代理**(持久上下文、可持续) |
|
|
21
|
+
| 任务分工 | 代码指定 | 代码指定 | 规划器指定 | **常驻们开会/留言决定** |
|
|
22
|
+
| 验证 | 多验证器投票→裁决 | 多验证器辩论→裁决(forced/flat) | 多验证器辩论→近共识裁决 | **全体常驻一致才定论**,否则留库附概率 |
|
|
23
|
+
| 产物归属 | 全局 | 全局 | 按路径 | **按常驻 id 归属**(每人自己的进展/命题/方法/子问题库) |
|
|
24
|
+
| 上下文管理 | 无 | 无 | 无 | **常驻上下文占比达阈值自动 `/compact`** |
|
|
25
|
+
| 停止 | 全解或卡死 | 全解或卡死 | 全解/无候选 | **全体常驻一致认为原问题已解决**才停 |
|
|
26
|
+
| 人工干预 | manual 门 | manual 门 | manual 门 | **随时可留言/提要求/开会/增开关闭常驻** |
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 2. 设计原则(你的哲学 → 架构规则)
|
|
31
|
+
|
|
32
|
+
1. **常驻主体**:起始产生 N 个常驻子代理,先各自对原问题头脑风暴,产出初始见解/方向;此后一直保持工作,直到全体认为解决。
|
|
33
|
+
2. **完全内部自组织**:之后所有任务安排(含朝某方向探索、尝试、分工、验证)都由它们之间**留言 + 开会**决定;框架不指派。
|
|
34
|
+
3. **自我验证 + 按价值沉淀**:每次思考产出的有价值内容,**自己**决定是否记入**自己**的 progress / 命题库 / 方法库 / 子问题库;记录至少注明 **价值程度 / 动机用途计划 / 自身概率估计**。
|
|
35
|
+
4. **互相可见**:常驻可查看、阅读彼此的 progress / 命题 / 方法 / 子问题库(只读)。
|
|
36
|
+
5. **验证 = 全体一致**:验证由常驻们**自行商议**何时、对哪个对象发起辩论;**只有全部常驻一致判真(或一致判假)**才写入 `Verified/`;否则留在库中并附概率 + 辩论记录。
|
|
37
|
+
6. **上下文管理**:常驻上下文量达阈值(默认 66%,可调)→ 对其实施 DSH `/compact`。
|
|
38
|
+
7. **可控**:允许助手/人工中途干预(留言、提要求、开会、增开/关闭某常驻);不影响"之后一切由它们自组织"。
|
|
39
|
+
8. **持续化**:所有产物 + 常驻注册表 + 邮件箱 + 任务板 + 会议录持久化,支持断点续跑;多项目/多会话隔离。
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## 3. 架构图
|
|
44
|
+
|
|
45
|
+
```mermaid
|
|
46
|
+
flowchart TD
|
|
47
|
+
subgraph 常驻层[常驻子代理(continuable,持久上下文)]
|
|
48
|
+
R1[R-1 方向A] ; R2[R-2 方向B] ; R3[R-3 方向C] ; RN[... R-N]
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
subgraph 媒介层[框架 vibe-v4(媒介/沉淀/共识/上下文)]
|
|
52
|
+
BUS[消息总线·邮件箱]
|
|
53
|
+
MTG[会议/辩论]
|
|
54
|
+
TASK[任务板]
|
|
55
|
+
PERSIST[产物沉淀]
|
|
56
|
+
VERIFY[共识验证]
|
|
57
|
+
COMPACT[/compact 监测]
|
|
58
|
+
STATE[State 注册表/锁/恢复]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
subgraph 共享知识库[VibeMath/Projects/<project>]
|
|
62
|
+
PROJ[Problems/ 原问题]
|
|
63
|
+
SPROJ[Subproblems/ 各常驻子问题]
|
|
64
|
+
PROP[Propos/ 各常驻命题库]
|
|
65
|
+
METH[Methods/ 各常驻方法库]
|
|
66
|
+
PRG[Progress/ 各常驻进展]
|
|
67
|
+
VERF[Verified/ 仅共识后只读]
|
|
68
|
+
SHARED[Shared/ 会议·任务板·决策·辩论]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
R1 & R2 & R3 & RN <-->|留言/开会/任务| BUS
|
|
72
|
+
BUS -->|唤醒 followup| R1
|
|
73
|
+
BUS -->|唤醒| R2
|
|
74
|
+
MTG -->|议程/结论| SHARED
|
|
75
|
+
R1 & R2 & R3 & RN -->|按价值沉淀| PROP
|
|
76
|
+
R1 & R2 & R3 & RN -->|记录| METH & SPROJ & PRG
|
|
77
|
+
R1 & R2 & R3 & RN -.->|只读他人的库| PRG & PROP & METH & SPROJ
|
|
78
|
+
VERIFY -->|全票真/假| VERF
|
|
79
|
+
VERIFY -.->|未全票→留库附概率| PROP
|
|
80
|
+
COMPACT -->|达66%| R1
|
|
81
|
+
STATE -->|断点重建| R1 & R2 & R3 & RN
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 4. 常驻子代理模型
|
|
87
|
+
|
|
88
|
+
### 4.1 本质
|
|
89
|
+
- 每个常驻 = 一个 DSH **continuable 子代理**:`subagents.startContinuable({ parent: 会话根代理, request, agentOptions, toolFilter })`。
|
|
90
|
+
- **持久上下文**(continuable):跨多次唤醒记住前文,直到被 `/compact` 压缩。
|
|
91
|
+
- **唤醒** = `subagents.followup(root, <childId>, [textBlock(prompt)])`;一轮收益 = 该常驻提交一次完整思考(经 `ctx.on('subagent/end')` 回归)。
|
|
92
|
+
- **工具**:`tools.register` 对会话内所有代理可用(处理器按 `exec.agent` 路由),故常驻可直接用 `fs` + `vibe_v4_*` 工具(写自己的库、读他人的库、发消息、提会议、记命题、发起验证)。
|
|
93
|
+
|
|
94
|
+
### 4.2 身份与上下文
|
|
95
|
+
```
|
|
96
|
+
id: r-<n> (n=1..N,可增开/关闭)
|
|
97
|
+
方向: 初始头脑风暴所得方向
|
|
98
|
+
初始上下文 = 常驻章程(§6) + 原问题完整陈述 + 本方向 + "先独立想,产出你的见解/思路/方向"
|
|
99
|
+
每轮上下文 = 常驻章程(精简) + 本人最新成果梗概 + 新到达的消息/会议录/任务认领 + "做一轮:思考→自验→按价值沉淀→交流/表决"
|
|
100
|
+
上下文占比 ≥ compactThreshold(默认66%) → 框架触发 DSH /compact
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 4.3 专属产物(持久,按常驻隔离)
|
|
104
|
+
```
|
|
105
|
+
VibeMath/Projects/<project>/
|
|
106
|
+
Progress/<r-id>/progress.md # 本人持续进展(追加式)
|
|
107
|
+
Propos/<r-id>/<p-id>.md # 本人命题
|
|
108
|
+
Methods/<r-id>/<m-id>.md # 本人理论/方法/工具
|
|
109
|
+
Subproblems/<r-id>/<s-id>.md # 本人子问题
|
|
110
|
+
# 常驻只写自己的目录;对其它常驻目录只读
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## 5. 框架(vibe-v4 插件)= 媒介,绝不分配任务
|
|
116
|
+
|
|
117
|
+
| 能力 | 机制 | 关键点 |
|
|
118
|
+
|---|---|---|
|
|
119
|
+
| **常驻生命周期** | start 时 brainstorm→spawn N(各带初始方向);add/remove;resume 重建 | 常驻上下文断点后需 re-spawn 并用其 `progress.md` 重种化 |
|
|
120
|
+
| **消息总线** | `vibe_v4_send_message(to, content)` → 入目标邮件箱 → 若空闲则 `followup` 唤醒 | 常驻间不直接互调,全靠框架 relay(模拟收件箱);支持 `broadcast(all)` |
|
|
121
|
+
| **会议** | `vibe_v4_meeting(agenda)` → 向全体发会议 prompt → 收齐发言 → 写 `Shared/meetings/<id>.md` → 广播结论 | 会议用于分工/方向/任务分配/提出验证/表决"是否已解决" |
|
|
122
|
+
| **任务板** | 常驻在会议/留言提议任务 → 框架记 `Shared/taskboard.md`;认领后被唤醒 | 框架只搬运,不决定谁做什么 |
|
|
123
|
+
| **产物沉淀** | `vibe_v4_publish_progress` / `record_proposition` / `record_method` / `record_subproblem` | **必填**:价值程度 / 动机用途计划 / 自身概率估计(框架校验,缺则提示) |
|
|
124
|
+
| **共识验证** | `vibe_v4_propose_verify(targetId)` → 常驻们同意后开辩论 | 独立初评→公开辩论→**全票真/假才入 Verified/**;否则留库附概率 |
|
|
125
|
+
| **停止条件** | 会议中全体常驻对"原问题已解决"投票,**全部同意** → 停止唤醒 | 人工 `abort` 始终可用 |
|
|
126
|
+
| **上下文/compact** | 监测每常驻上下文占比 ≥ 阈值 → 触发 DSH `/compact` | `compactThreshold` 默认 66,可调 |
|
|
127
|
+
| **人工/助手干预** | `vibe_v4_message(all, content)` / `vibe_v4_meeting` / `vibe_v4_add_member` / `remove_member` / `vibe_v4_inject`;`/v4` slash | 不改变"之后由它们自组织" |
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## 6. 常驻章程(写入每个常驻初始上下文)
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
你是常驻研究者 R-<k>(共 N 位),与其它常驻协作解决问题:<原问题完整陈述>。
|
|
135
|
+
你的方向/起点:<初始头脑风暴方向>。
|
|
136
|
+
|
|
137
|
+
【信任规则】只有 Verified/(及 Propos 中"已验证·真/假")绝对可信;你自己未验证的、他人的未验证产物都是经验性参考,不能当作已成立事实引用。
|
|
138
|
+
|
|
139
|
+
【每轮默认动作】
|
|
140
|
+
① 思考本方向下一步(或回应他人/会议);
|
|
141
|
+
② 自我验证刚得到的结论,并"按价值"决定是否记入自己的 progress/命题/方法/子问题库;
|
|
142
|
+
凡入册必须写明:价值程度、动机用途计划、你对该对象为真的概率估计;
|
|
143
|
+
③ 决定是否要给某常驻留言 / 提议开会 / 提议对某对象开展共识验证辩论;
|
|
144
|
+
④ 会议或辩论中发言,对任务分工/方向/停止条件表态。
|
|
145
|
+
|
|
146
|
+
【验证规则】任何对象要进 Verified/ 必须全体常驻一致判真或判假;否则留在库中并附概率。你只信"全票同意"的。
|
|
147
|
+
|
|
148
|
+
【任务自主】下一轮你自己做什么、与他人怎么分工,由你们开会/留言决定——没有外部派活。
|
|
149
|
+
|
|
150
|
+
【可见性】你可以读所有常驻的 progress/命题/方法/子问题库;只写自己的库。
|
|
151
|
+
|
|
152
|
+
【停止】当且仅当全体一致认为原问题已解决,才会停止调度。
|
|
153
|
+
|
|
154
|
+
【干预】助手/人可能给你留言、提要求、要求开会、或增开/关闭常驻——服从并响应。
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
> 每轮回调 prompt = 常驻章程(可精简)+ 本人最新成果梗概 + 新到达输入 + "做一轮,并在结束时给出你对『原问题是否已解决』的最新看法"。
|
|
158
|
+
|
|
159
|
+
---
|
|
160
|
+
|
|
161
|
+
## 7. 数据模型 / Schema(软规范:头部锚点行 + 正文自由叙述;解析器同 v3 风格)
|
|
162
|
+
|
|
163
|
+
**常驻注册表 `State/residents.json`**
|
|
164
|
+
```json
|
|
165
|
+
{ "r-1": { "rId":"r-1", "childId":"...", "direction":"...", "status":"brainstorm|active|idle|compact",
|
|
166
|
+
"createdAt":..., "lastActiveAt":..., "contextPct":0.3 } }
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**邮件箱 `State/mailboxes.json`**
|
|
170
|
+
```json
|
|
171
|
+
{ "r-1": [ { "from":"r-2", "at":..., "content":"...", "delivered":false } ] }
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**任务板 `Shared/taskboard.md`**
|
|
175
|
+
```
|
|
176
|
+
- [open|claimed|done] <任务简述> (提议人: r-2, 认领人: r-3, 涉及方向: d3, 来源: 会议<id>/留言)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
**命题卡 `Propos/<r-id>/<p-id>.md`**
|
|
180
|
+
```
|
|
181
|
+
- ID: p-xxx
|
|
182
|
+
- 类型: 命题
|
|
183
|
+
- 状态: 未定论|已验证·真|已验证·假
|
|
184
|
+
- 概率: 0.62
|
|
185
|
+
- 价值程度: 0.7
|
|
186
|
+
- 动机用途计划: ...(为何有价值/拟如何用于解决问题/如何回填主线)
|
|
187
|
+
- 依赖: []
|
|
188
|
+
## 陈述 (完整)
|
|
189
|
+
## 证明尝试 (### 证明 N|…|概率X|状态Y)
|
|
190
|
+
## 证伪尝试 (### 证伪 N|…|概率X|状态Y)
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
**方法卡 `Methods/<r-id>/<m-id>.md`**
|
|
194
|
+
```
|
|
195
|
+
- ID: m-xxx
|
|
196
|
+
- 类型: 理论体系|框架|工具|方法|思想|范式|技巧
|
|
197
|
+
- 状态: 经验|应用验证|含已验证断言
|
|
198
|
+
- 可信断言: [](只允许进过 Verified/ 的 id)
|
|
199
|
+
- 价值程度: 0.6
|
|
200
|
+
- 动机用途计划: ...
|
|
201
|
+
## 核心内容
|
|
202
|
+
## 定义与记号
|
|
203
|
+
## 应用记录
|
|
204
|
+
## 改进历史
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
**子问题卡 `Subproblems/<r-id>/<s-id>.md`**
|
|
208
|
+
```
|
|
209
|
+
- ID: s-xxx
|
|
210
|
+
- 状态: 未定论|求解中|已解决
|
|
211
|
+
- 价值程度: 0.5
|
|
212
|
+
- 动机用途计划: ...(如何回填主线 / 独立求解后如何反哺)
|
|
213
|
+
- 依赖: []
|
|
214
|
+
## 陈述 (完整)
|
|
215
|
+
## 进度
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
**共享写锁**:仅对 `Shared/*`、`Problems/<id>.md`、`Verified/*` 使用 `vibe_v4_claim_write/release_write`(进程级 fileOwner,同 v3);各常驻目录内天然无冲突。
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## 8. 共识验证(Verification)算法
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
1. 提议:常驻们经留言/会议达成"值得验证"的共识,对 target(命题/证明/方法/理论) 开启验证。
|
|
226
|
+
2. 框架建 Shared/debates/<target>.md;【独立初评】向每个常驻各发一次(不看他人):
|
|
227
|
+
给 verdict(真/假/不确定) + 理由 + 概率。
|
|
228
|
+
3. 若已全票真 → 写入 Verified/命题(或方法→可信断言)/<id>.md,并回写来源库项状态=已验证·真。
|
|
229
|
+
若已全票假 → 写入 Verified/命题/<id>.md(结论=假),来源库项状态=已验证·假。
|
|
230
|
+
(问题类 target 同理:Verified/问题/<id>.md)
|
|
231
|
+
4. 否则【公开辩论】:把初评意见+理由写入辩论录,广播全体;各常驻看他人意见后重评
|
|
232
|
+
(可引用/反驳/修改),直至:全票同向,或不再出现理性新分歧。
|
|
233
|
+
5. 未全票 → 保留在来源库,概率取各常驻最后估计的平均,附"未达成全体一致"的辩论记录。
|
|
234
|
+
【要点】不设 v3 的 forced/flat/近共识自动收口——必须真实全体一致,防止强分歧被强行判真。
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 9. 并发 / 活性 / 隔离 / 恢复
|
|
240
|
+
|
|
241
|
+
- **活性(防僵死)**:每次 `subagent/end` 后,框架优先:
|
|
242
|
+
① 任何邮件箱非空 → 唤醒非忙收件人;
|
|
243
|
+
② 否则任务板有 open → 唤醒提议人/认领人;
|
|
244
|
+
③ 否则存在待验证提议 → 开会;
|
|
245
|
+
④ 否则"心跳":唤醒最久未活跃者并给它开会,让它表态下一步(`activityTimeoutMs` 可调)。
|
|
246
|
+
- **并行**:同一时刻可唤醒多个空闲常驻(受 `maxParallel` 上限,默认 3,框架侧并发闸,非"指派")。
|
|
247
|
+
- **隔离**(同 v3):`sessions`(根代理→Session)、`childOwner`(子代理→会话路由 subagent/end)、`fileOwner`(进程级写锁跨会话)、`projectLock`(每会话)、`processEpoch`(进程级,防两会话互判陈旧)。
|
|
248
|
+
- **断点续跑**:`vibe_v4_resume` 用 `State/residents.json` + 各常驻 `progress.md` 重建常驻(re-spawn + 重种化上下文),恢复邮件箱/任务板/会议录;`processEpoch` 判断是否清空中在途轮。
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## 10. 与 DSH 机制映射(实现时确认)
|
|
253
|
+
|
|
254
|
+
| DSH 能力 | 在本架构中的用途 |
|
|
255
|
+
|---|---|
|
|
256
|
+
| `subagents.startContinuable({parent, request, agentOptions, toolFilter})` | 产生常驻(continuable,持久上下文) |
|
|
257
|
+
| `subagents.followup(root, childId, blocks)` | 唤醒常驻做一轮 / 投递一条留言 / 开会向某常驻收集发言 |
|
|
258
|
+
| `ctx.on('subagent/end')` | 一常驻完成一轮(收其回复,续驱动) |
|
|
259
|
+
| `subagents.interrupt / list` | 中断 / 枚举常驻 |
|
|
260
|
+
| `tools.register`(会话内所有代理可用,`exec.agent` 路由) | 常驻可直接调用 `vibe_v4_*` 与 `fs` |
|
|
261
|
+
| `commands.register` | `/v4` slash 控制命令 |
|
|
262
|
+
| `contextPct` + DSH `/compact` | 上下文占比达 66% 自动压缩(精确触发点实现时确认) |
|
|
263
|
+
| `claimWrite/releaseWrite` + 项目锁(复用 v3 模式) | 共享文件写锁 + 会话项目锁 |
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## 11. 实现阶段(只策划,不在此文档内写代码)
|
|
268
|
+
|
|
269
|
+
- **P0 脚手架**:`vibe-math-v4/`(`agent.cordis.yml`、`preset.yml`、`vibe-math-v4.js`);`installer.js` 增加 v4 安装/能力自检;`package.json files` 增加 v4;README 增 V4 小节。
|
|
270
|
+
- **P1 常驻生命周期**:brainstorm→spawn N(各带方向)→track→wake→(`subagent/end`)→compact→resume;brainstormPhase 只产出初始方向并持久。
|
|
271
|
+
- **P2 消息总线 + 邮件箱 + 跨读**:`send_message`/mailbox/唤醒;他人库只读工具;写锁。
|
|
272
|
+
- **P3 会议 + 任务板 + 决策**:`meeting`/taskboard/decisions;分工涌现。
|
|
273
|
+
- **P4 产物沉淀**:`record_proposition/method/subproblem` + `publish_progress`(价值/动机/概率必填校验)。
|
|
274
|
+
- **P5 共识验证**:`propose_verify` + 独立初评 + 公开辩论 + 全票闭环;`Verified/` 生成与来源库回写。
|
|
275
|
+
- **P6 停止 + 干预 + 恢复**:stop-vote(全票 solved)/abort/pause/resume;`add_member/remove_member/inject/message(all)`。
|
|
276
|
+
- **P7 测试**:`selfdrive-v4.mjs`(常驻互相留言/开会/沉淀/共识验证/compact/停止 的全流程记录器);E2E 断言:消息送达、会议记录、仅全票入 Verified、未全票留库附概率、compact 触发、仅全体一致才 stop、resume。
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 12. 边界 / 失败 / 风险
|
|
281
|
+
|
|
282
|
+
| 场景 | 处理 |
|
|
283
|
+
|---|---|
|
|
284
|
+
| 全员等待、无人行动(僵死) | §9 活性机制(mailbox→taskboard→verify提案→心跳会议)兜底 |
|
|
285
|
+
| 共识永达不成 | 对象留库附概率,不阻塞其它工作;不强行裁决 |
|
|
286
|
+
| 上下文 blow-up | compact 阈值 + 每轮只带"梗概+新输入";会议/辩论录按需截断 |
|
|
287
|
+
| 共享文件并发 | 写锁;各常驻专属文件无锁 |
|
|
288
|
+
| 常驻崩溃/退出 | `subagent/end` 异常置 `idle`;`resume` 重建 |
|
|
289
|
+
| 常驻误用工具 | 默认继承会话工具;可用 `toolFilter` 收权为 `fs` + `vibe_v4_*` + 只读库工具 |
|
|
290
|
+
| 多项目并发 | 各项目 `State/`+`Shared/` 隔离;`projectLock` 防两会话跑同一项目 |
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 13. 参数默认值
|
|
295
|
+
|
|
296
|
+
| 参数 | 建议默认 | 说明 |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| `residentCount` | 4 | 常驻数(可 `add_member` 增减) |
|
|
299
|
+
| `compactThreshold` | 66 | 常驻上下文占比达此值触发 `/compact` |
|
|
300
|
+
| `maxParallel` | 3 | 同时唤醒的常驻上限(框架侧并发闸,非指派) |
|
|
301
|
+
| `activityTimeoutMs` | 120000 | 无新消息/任务/提案时的心跳间隔 |
|
|
302
|
+
| `verdictQuorum` | `all` | 固定"全部常驻一致"(哲学要求,不建议放宽) |
|
|
303
|
+
| `perResidentLibs` | 每常驻独立目录 | 若"共享库+署名"会重新引入写锁竞争,不推荐 |
|
|
304
|
+
|
|
305
|
+
---
|
|
306
|
+
|
|
307
|
+
## 14. 成功标准(验收)
|
|
308
|
+
|
|
309
|
+
1. 起始产生 N 个常驻,先各自头脑风暴、产出初始见解/方向。
|
|
310
|
+
2. 此后所有任务安排(探索/尝试/分工/验证)由常驻们互相留言/开会决定,无中央调度器。
|
|
311
|
+
3. 每个常驻有专属、持久的 progress/命题/方法/子问题库,可互相阅读。
|
|
312
|
+
4. 记录产物必带 价值程度 / 动机用途计划 / 自身概率估计。
|
|
313
|
+
5. 验证由常驻自行商议发起;仅全体一致(真 或 假)才入 `Verified/`;否则留库附概率。
|
|
314
|
+
6. 常驻上下文达 66%(可调)自动 `/compact`。
|
|
315
|
+
7. 允许助手/人工中途干预(留言/提要求/开会/增开关闭常驻)。
|
|
316
|
+
8. 仅当全体常驻一致认为原问题已解决才停止调度。
|
|
317
|
+
9. 支持断点续跑、多会话/多项目隔离、共享文件写锁 + 常驻专属文件隔离。
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
## 15. 待确认项(实现前与用户敲定;已给建议默认)
|
|
322
|
+
|
|
323
|
+
- 常驻数默认 4,是否直接给用户一个 `residentCount` 参数。
|
|
324
|
+
- 是否允许"只读他人库但需授权"(哲学已允许互相阅读,默认全读)。
|
|
325
|
+
- `verdictQuorum` 是否始终为 `all`(哲学强调一致,默认不改)。
|
|
326
|
+
- `perResidentLibs`(每常驻独立目录 vs 共享库+署名)——默认独立。
|
|
327
|
+
- DSH `/compact` 的精确触发 API(实现 P1 时确认)。
|