- commit
- b3f2e2f
- parent
- 4ac55fa
- author
- codex@macbookpro
- date
- 2026-03-27 15:17:47 +0800 CST
docs: add baa instruction system v5
27 files changed,
+2695,
-0
+59,
-0
1@@ -0,0 +1,59 @@
2+# BAA 指令系统设计方案 v5(语法兼容 v3)
3+
4+日期:2026-03-27
5+
6+这是在上一版 v4 的基础上,进一步把 **结果产物管理收口到 conductor** 后的完整版。
7+
8+## 这版最关键的变更
9+
10+1. **插件降级成纯传输层 / 文件传输层**
11+ - 插件只负责:
12+ - 页面桥接
13+ - 最终消息观察
14+ - 上传文件
15+ - 下载文件
16+ - 注入文本 / 点击发送
17+ - 插件不负责:
18+ - baa 提取
19+ - 指令解析
20+ - 去重
21+ - 结果总结
22+ - 大结果提取
23+ - artifact 打包
24+ - manifest 生成
25+
26+2. **conductor 成为唯一的结果产物管理中心**
27+ - conductor 统一负责:
28+ - 解析 / 标准化 / 路由 / 权限 / 审计
29+ - 执行结果总结
30+ - 大结果转 artifact
31+ - manifest / 索引文本生成
32+ - delivery plan 生成
33+ - 上传确认后的最终注入文本
34+
35+3. **结果交付升级为 `artifact + index + manifest + ack`**
36+ - 小结果:直接文本
37+ - 中 / 大结果:artifact 上传 + 文本索引
38+ - 多结果并行:manifest 汇总
39+ - 上传成功后才发送索引文本
40+
41+## 这个包里有什么
42+
43+- `docs/00-executive-summary.md`:执行摘要
44+- `docs/01-design-principles.md`:原则与边界
45+- `docs/02-protocol-spec.md`:协议规范
46+- `docs/03-routing-capability-borrowing.md`:路由与能力借用
47+- `docs/04-execution-loop-state-machine.md`:状态机
48+- `docs/05-auth-governance-and-safety.md`:权限与治理
49+- `docs/06-integration-with-current-baa-conductor.md`:与当前 repo 的对接方式
50+- `docs/07-rollout-plan.md`:渐进式落地阶段
51+- `docs/08-examples.md`:直接可用示例
52+- `docs/09-artifact-delivery-thin-plugin.md`:结果交付与薄插件专项说明
53+- `contracts/`:类型与伪代码
54+- `schemas/`:JSON schema
55+- `prompts/`:提示词模板
56+- `reference/`:原始 v3 文档与本版变更说明
57+
58+## 一句话结论
59+
60+> **v3 解决“怎么输出可执行指令”,v4 解决“怎么稳定执行”,v5 解决“怎么让插件变薄、让 conductor 成为真正的中控与产物管理中心”。**
1@@ -0,0 +1,64 @@
2+import type { ArtifactManifest, ArtifactRef, DeliveryPlan, ExecutionResult, UploadReceipt } from "./types";
3+
4+ export function materializeArtifacts(results: ExecutionResult[]): ArtifactRef[] {
5+ // pseudo:
6+ // - choose summary.md / payload.ext / manifest.json
7+ // - write files to artifact store
8+ // - return refs with artifactId/localPath/mimeType
9+ return [];
10+ }
11+
12+ export function buildManifest(results: ExecutionResult[], refs: ArtifactRef[]): ArtifactManifest {
13+ return {
14+ manifestId: "mf_TODO",
15+ traceId: "trace_TODO",
16+ roundId: null,
17+ entries: results.map(r => ({
18+ instructionId: r.instructionId,
19+ ok: r.ok,
20+ summary: r.summary,
21+ artifactIds: (r.artifactRefs ?? []).map(a => a.artifactId)
22+ }))
23+ };
24+ }
25+
26+ export function renderIndexText(results: ExecutionResult[], manifest: ArtifactManifest): string {
27+ const lines = ["[BAA 结果索引]"];
28+ for (const r of results) {
29+ lines.push(`- instruction_id: ${r.instructionId}`);
30+ lines.push(`- 结果: ${r.ok ? "成功" : "失败"}`);
31+ lines.push(`- 摘要: ${r.summary}`);
32+ }
33+ lines.push(`- manifest: ${manifest.manifestId}.json`);
34+ return lines.join("
35+");
36+ }
37+
38+ export function buildDeliveryPlan(input: {
39+ target: string;
40+ conversationId: string | null;
41+ traceId: string;
42+ uploadRefs: ArtifactRef[];
43+ indexText: string;
44+ }): DeliveryPlan {
45+ return {
46+ planId: "plan_TODO",
47+ traceId: input.traceId,
48+ conversationId: input.conversationId,
49+ target: input.target,
50+ uploads: input.uploadRefs
51+ .filter(r => r.localPath)
52+ .map(r => ({
53+ artifactId: r.artifactId,
54+ filename: r.filename,
55+ mimeType: r.mimeType,
56+ localPath: r.localPath!
57+ })),
58+ messageText: input.indexText,
59+ autoSend: true
60+ };
61+ }
62+
63+ export function shouldSendIndex(receipts: UploadReceipt[]): boolean {
64+ return receipts.every(r => r.ok);
65+ }
1@@ -0,0 +1,82 @@
2+import type { DeliveryPlan, ExecutionResult, NormalizedInstruction, RouteDecision, UploadReceipt } from "./types";
3+
4+export function computeDedupeKey(input: {
5+ platform: string;
6+ conversationId: string | null;
7+ assistantMessageId: string | null;
8+ blockIndex: number;
9+ normalizedBlockText: string;
10+}): string {
11+ // pseudo: sha256(platform|conversationId|assistantMessageId|blockIndex|normalizedBlockText)
12+ return "sha256:TODO";
13+}
14+
15+export async function routeInstruction(inst: NormalizedInstruction): Promise<RouteDecision> {
16+ if (["conductor", "system", "orchestrator"].includes(inst.target)) {
17+ return {
18+ resolvedTarget: "conductor",
19+ routeReason: ["exact local target matched"],
20+ fallbackCandidates: []
21+ };
22+ }
23+
24+ if (inst.target.startsWith("browser.")) {
25+ return {
26+ resolvedTarget: inst.target,
27+ routeReason: ["platform bridge target matched"],
28+ fallbackCandidates: []
29+ };
30+ }
31+
32+ if (inst.target.startsWith("pool.")) {
33+ return {
34+ resolvedTarget: "browser.chatgpt",
35+ resolvedNodeId: "chatgpt.agent.beta",
36+ routeReason: ["logical pool resolved by capability_match", "recent_success high"],
37+ fallbackCandidates: ["browser.gemini"]
38+ };
39+ }
40+
41+ return {
42+ resolvedTarget: "manual",
43+ routeReason: ["no legal route found"],
44+ fallbackCandidates: []
45+ };
46+}
47+
48+export async function executeNormalizedInstruction(inst: NormalizedInstruction): Promise<ExecutionResult> {
49+ const route = await routeInstruction(inst);
50+
51+ if (route.resolvedTarget === "manual") {
52+ return {
53+ instructionId: inst.instructionId,
54+ ok: false,
55+ target: inst.target,
56+ tool: inst.tool,
57+ summary: "No legal route found.",
58+ errorCode: "route_not_found",
59+ deliveryMode: "inline"
60+ };
61+ }
62+
63+ return {
64+ instructionId: inst.instructionId,
65+ ok: true,
66+ target: route.resolvedTarget,
67+ tool: inst.tool,
68+ summary: "Executed via resolved route.",
69+ data: { routeReason: route.routeReason, fallbackCandidates: route.fallbackCandidates },
70+ deliveryMode: "inline"
71+ };
72+}
73+
74+export function canInjectAfterReceipts(receipts: UploadReceipt[]): boolean {
75+ return receipts.length > 0 && receipts.every(r => r.ok);
76+}
77+
78+export function finalizeDelivery(plan: DeliveryPlan, receipts: UploadReceipt[]): { text: string; send: boolean } {
79+ if (!canInjectAfterReceipts(receipts)) {
80+ throw new Error("upload_not_confirmed");
81+ }
82+ return { text: plan.messageText, send: plan.autoSend };
83+}
1@@ -0,0 +1,103 @@
2+export type RiskTier = "tier0" | "tier1" | "tier2" | "tier3";
3+export type DeliveryMode = "inline" | "inline_and_artifact" | "artifact_only";
4+
5+export interface ParsedBaaInstruction {
6+ rawBlock: string;
7+ blockIndex: number;
8+ target: string;
9+ tool: string;
10+ params: Record<string, unknown>;
11+}
12+
13+export interface NormalizedInstruction extends ParsedBaaInstruction {
14+ instructionId: string;
15+ traceId: string;
16+ conversationId: string | null;
17+ assistantMessageId: string | null;
18+ sourceNode: string;
19+ roundId: string | null;
20+ hop: number;
21+ riskTier: RiskTier;
22+ dedupeKey: string;
23+ createdAt: number;
24+}
25+
26+export interface RouteDecision {
27+ resolvedTarget: string;
28+ resolvedNodeId?: string;
29+ routeReason: string[];
30+ fallbackCandidates: string[];
31+}
32+
33+export interface ArtifactRef {
34+ artifactId: string;
35+ kind: "summary" | "payload" | "manifest" | "preview" | "log" | "image" | "video" | "other";
36+ filename: string;
37+ mimeType: string;
38+ sizeBytes?: number;
39+ sha256?: string;
40+ localPath?: string;
41+ remoteHandle?: string | null;
42+}
43+
44+export interface ExecutionResult {
45+ instructionId: string;
46+ ok: boolean;
47+ target: string;
48+ tool: string;
49+ summary: string;
50+ data?: unknown;
51+ truncated?: boolean;
52+ deliveryMode: DeliveryMode;
53+ artifactRefs?: ArtifactRef[];
54+ errorCode?: string;
55+}
56+
57+export interface ArtifactManifestEntry {
58+ instructionId: string;
59+ ok: boolean;
60+ summary: string;
61+ artifactIds: string[];
62+}
63+
64+export interface ArtifactManifest {
65+ manifestId: string;
66+ traceId: string;
67+ roundId: string | null;
68+ entries: ArtifactManifestEntry[];
69+}
70+
71+export interface DeliveryUploadItem {
72+ artifactId: string;
73+ filename: string;
74+ mimeType: string;
75+ localPath: string;
76+}
77+
78+export interface DeliveryPlan {
79+ planId: string;
80+ traceId: string;
81+ conversationId: string | null;
82+ target: string;
83+ uploads: DeliveryUploadItem[];
84+ messageText: string;
85+ autoSend: boolean;
86+}
87+
88+export interface UploadReceipt {
89+ artifactId: string;
90+ ok: boolean;
91+ remoteHandle?: string;
92+ errorCode?: string;
93+}
94+
95+export interface DownloadItem {
96+ remoteHandle: string;
97+ suggestedFilename: string;
98+ savePath: string;
99+}
100+
101+export interface DownloadPlan {
102+ downloadPlanId: string;
103+ items: DownloadItem[];
104+}
1@@ -0,0 +1,71 @@
2+# 00. 执行摘要
3+
4+## 背景判断
5+
6+你当前上传的《BAA 指令 v3》已经把最重要的三件事抓住了:
7+
8+1. 用 ` ```baa ` 做类型声明。
9+2. 用 **一个代码块 = 一条指令** 建立稳定粒度。
10+3. 用浏览器插件 + conductor 消灭人工复制粘贴。
11+
12+这些都要保留。
13+
14+## 这次真正补上的东西
15+
16+这一版不是再改语法,而是把系统边界重新画清楚。
17+
18+### 1. 双平面模型保持不变
19+- **控制面**:` ```baa ` 指令块
20+- **内容面**:自然语言、`[REQUEST_CONTEXT]`、`[STRESS_TEST]`、共识文本等
21+
22+### 2. 能力借用保持为一级能力
23+- `@conductor::exec`
24+- `@browser.chatgpt::send`
25+- `@pool.image::generate`
26+- `@role.reviewer::ask`
27+
28+### 3. conductor 成为唯一的解释与治理中心
29+conductor 统一负责:
30+- baa 提取与解析
31+- 标准化 envelope
32+- 去重
33+- 权限 / 路由 / 审计
34+- 执行与结果总结
35+- artifact 打包与 manifest
36+- delivery plan
37+
38+### 4. 插件退化成薄层 courier
39+插件只做:
40+- 页面桥接
41+- 观察最终权威消息
42+- 上传 artifacts
43+- 下载 browser 侧产物
44+- 注入准备好的文本并发送
45+
46+### 5. 结果交付正式变成两层
47+- **控制层**:`[BAA 结果索引]` + 可选 `baa-result` 代码块
48+- **载荷层**:artifact 文件 + manifest
49+
50+### 6. 上传确认成为状态机的一部分
51+不是“文件 drop 进输入框”就算成功。
52+只有插件确认平台附件已挂载成功,conductor 才能发最终索引文本。
53+
54+## 最终结构判断
55+
56+推荐采用:
57+
58+### Phase 1:立即把解析中心移入 conductor
59+不再做“插件侧 parser MVP”这条临时路线。
60+
61+### Phase 2:插件只保留 transport / upload / download / inject
62+让插件变哑,让 conductor 变强。
63+
64+### Phase 3:能力池与多平台接入
65+正式支持 `browser.chatgpt` / `browser.gemini` / `pool.*`。
66+
67+### Phase 4:与多 AI 自洽协作层联动
68+round / chain / gossip / consensus 统一纳入编排。
69+
70+## 一句话结论
71+
72+**不要再让插件长脑子;要让 conductor 成为唯一的大脑。**
1@@ -0,0 +1,107 @@
2+# 01. 设计原则
3+
4+## 1. 语法极简,系统复杂度后移
5+AI 最容易记住的是代码块,不是复杂 DSL。
6+所以:
7+- 语法层保持极简
8+- 复杂度后移到 conductor 的解析、路由、权限、状态机、artifact 管理
9+
10+## 2. 一个代码块 = 一条指令
11+这条规则不能动。
12+
13+原因:
14+- 并行语义天然成立
15+- 去重粒度稳定
16+- 风险边界清晰
17+- 一个块可以直接映射为一个 work item
18+
19+## 3. 双平面模型
20+
21+### 控制面(control plane)
22+是可执行、可路由、可审计的:
23+
24+```baa
25+@conductor::exec::pwd
26+```
27+
28+### 内容面(content plane)
29+是讨论、解释、共识、争议与上下文请求:
30+- 普通自然语言
31+- Markdown
32+- `[REQUEST_CONTEXT]`
33+- `[STRESS_TEST]`
34+- `[COUNTER_FACTUAL]`
35+- `LOCKED`
36+
37+**BAA 指令系统只负责控制面,不替代内容面。**
38+
39+## 4. 插件薄层,conductor 厚层
40+这是 v5 的核心原则。
41+
42+### 插件负责
43+- 页面桥接
44+- 最终消息观察
45+- 上传 / 下载
46+- 注入 / 发送
47+
48+### conductor 负责
49+- 提取与解析
50+- 去重与审计
51+- 路由与权限
52+- 总结与打包
53+- manifest 与 delivery plan
54+
55+## 5. 平台中立,能力导向
56+不要把能力写死成“某平台永远能做什么”。
57+系统应该依赖:
58+- capability declaration
59+- health
60+- availability
61+- recent success
62+- policy fit
63+
64+## 6. 精确寻址与能力路由共存
65+
66+### 精确寻址
67+```baa
68+@chatgpt.agent.beta::send::请生成一张图
69+```
70+
71+### 能力路由
72+```baa
73+@pool.image::generate::请生成一张图
74+```
75+
76+前者适合明确指派,后者适合能力借用与弹性切换。
77+
78+## 7. 只以最终权威消息为输入
79+不在 streaming 半截执行。
80+必须等:
81+- assistant 这轮完成
82+- 页面 / 平台拿到最终权威消息
83+- conductor 收到 raw message 后再提取 baa
84+
85+## 8. 幂等与审计是基础设施
86+每条指令都必须能回答:
87+- 来自哪条消息
88+- 第几个 block
89+- 是否执行过
90+- 谁批准的
91+- 结果是什么
92+- 上传了哪些 artifacts
93+- 发送了什么索引文本
94+
95+## 9. 大结果优先 artifact 化
96+不要默认把 stdout / JSON / diff / 图片全塞进对话。
97+推荐顺序:
98+- 能摘要就摘要
99+- 能 artifact 就 artifact
100+- 只把索引文本送回会话
101+
102+## 10. 人永远能接管
103+必须保留:
104+- pause
105+- resume
106+- drain
107+- stop current loop
108+- 人工编辑注入文本后再发送
1@@ -0,0 +1,350 @@
2+# 02. 协议规范
3+
4+ ## 2.1 语法目标
5+
6+ 保持和 v3 兼容:
7+
8+ ```text
9+ @target::tool::params
10+ ```
11+
12+ 并放在 ` ```baa ` 代码块中。
13+
14+ ## 2.2 文法(推荐)
15+
16+ ```ebnf
17+ instruction_block = "```baa" , newline , instruction_text , newline? , "```" ;
18+ instruction_text = first_line , ( newline , body )? ;
19+ first_line = "@" , target , "::" , tool , ( "::" , inline_params )? ;
20+ target = token , { "." , token } ;
21+ tool = token , { "/" , token } ;
22+ body = { any_char } ;
23+ token = 1*( ALPHA / DIGIT / "_" / "-" ) ;
24+ ```
25+
26+ ## 2.3 参数形式
27+
28+ ### A. 单行字符串参数
29+
30+ ```baa
31+ @conductor::exec::ls -la
32+ ```
33+
34+ ### B. 单行 JSON 参数
35+
36+ ```baa
37+ @conductor::files/read::{"path":"/tmp/a.txt"}
38+ ```
39+
40+ ### C. 多行参数
41+
42+ ```baa
43+ @conductor::exec
44+ cd /Users/george/code
45+ pnpm test
46+ ```
47+
48+ ## 2.4 推荐 target 命名
49+
50+ ### 精确 target
51+ - `conductor`
52+ - `system`
53+ - `orchestrator`
54+ - `browser.claude`
55+ - `browser.chatgpt`
56+ - `browser.gemini`
57+ - `chatgpt.agent.beta`
58+ - `claude.agent.alpha`
59+ - `gemini.agent.gamma`
60+ - `node.mini`
61+ - `node.mbp`
62+
63+ ### 逻辑 target
64+ - `pool.image`
65+ - `pool.video`
66+ - `pool.exec`
67+ - `pool.http`
68+ - `pool.review`
69+ - `role.reviewer`
70+ - `role.coder`
71+ - `role.artist`
72+
73+ ## 2.5 推荐 tool 分类
74+
75+ ### 本机与系统
76+ - `describe`
77+ - `status`
78+ - `pause`
79+ - `resume`
80+ - `drain`
81+ - `exec`
82+ - `files/read`
83+ - `files/write`
84+ - `tasks`
85+ - `tasks/read`
86+ - `tasks/logs`
87+
88+ ### 浏览器桥接
89+ - `open`
90+ - `send`
91+ - `current`
92+ - `request`
93+ - `reload`
94+ - `artifacts/upload`
95+ - `artifacts/download`
96+
97+ ### AI / 节点协作
98+ - `ask`
99+ - `send`
100+ - `delegate`
101+ - `chain/start`
102+ - `gossip/start`
103+ - `consensus/request`
104+ - `context/request`
105+
106+ ## 2.6 conductor 内部标准化 envelope
107+
108+ AI 原始输出很简洁,但 conductor 内部要转成稳定对象:
109+
110+ ```json
111+ {
112+ "instruction_id": "inst_01JQ...",
113+ "trace_id": "trace_01JQ...",
114+ "conversation_id": "conv_xxx",
115+ "assistant_message_id": "msg_xxx",
116+ "block_index": 0,
117+ "source_node": "claude.agent.alpha",
118+ "target": "pool.image",
119+ "tool": "generate",
120+ "params": {
121+ "prompt": "请生成一张赛博朋克风格城市夜景图"
122+ },
123+ "risk_tier": "tier1",
124+ "dedupe_key": "sha256:...",
125+ "round_id": "round_42",
126+ "hop": 3,
127+ "created_at": 1774570000000
128+ }
129+ ```
130+
131+ ## 2.7 结果对象与交付对象分离
132+
133+ v5 明确分成两层:
134+
135+ ### A. 执行结果(execution result)
136+ 由执行器产生,描述“做了什么,结果如何”。
137+
138+ ```json
139+ {
140+ "instruction_id": "inst_01JQ...",
141+ "target": "conductor",
142+ "tool": "exec",
143+ "ok": true,
144+ "summary": "pnpm test 完成,2 项失败。",
145+ "data": {
146+ "exit_code": 1,
147+ "stdout_preview": "..."
148+ },
149+ "delivery_mode": "artifact_only"
150+ }
151+ ```
152+
153+ ### B. 交付计划(delivery plan)
154+ 由 conductor 产生,描述“该上传什么、发什么文本、等什么确认”。
155+
156+ ```json
157+ {
158+ "plan_id": "plan_01JQ...",
159+ "trace_id": "trace_01JQ...",
160+ "conversation_id": "conv_xxx",
161+ "target": "browser.chatgpt",
162+ "uploads": [
163+ {
164+ "artifact_id": "art_01",
165+ "filename": "baa-result_trace_r03_b01_exec_conductor_fail.log",
166+ "mime_type": "text/plain",
167+ "local_path": "/tmp/baa/art_01.log"
168+ },
169+ {
170+ "artifact_id": "art_02",
171+ "filename": "baa-manifest_trace_r03.json",
172+ "mime_type": "application/json",
173+ "local_path": "/tmp/baa/manifest.json"
174+ }
175+ ],
176+ "message_text": "[BAA 结果索引]
177+- instruction_id: inst_01JQ...
178+- 摘要: pnpm test 完成,2 项失败。",
179+ "auto_send": true
180+ }
181+ ```
182+
183+ **插件只执行 delivery plan,不负责生成它。**
184+
185+ ## 2.8 artifact manifest
186+
187+ 多个大结果并行时,conductor 应生成 manifest:
188+
189+ ```json
190+ {
191+ "manifest_id": "mf_01JQ...",
192+ "trace_id": "trace_01JQ...",
193+ "round_id": "round_42",
194+ "results": [
195+ {
196+ "instruction_id": "inst_01",
197+ "ok": true,
198+ "summary": "读取 HANDOFF.md 成功",
199+ "artifact_ids": ["art_11"]
200+ },
201+ {
202+ "instruction_id": "inst_02",
203+ "ok": false,
204+ "summary": "pnpm test 失败,详见日志",
205+ "artifact_ids": ["art_12"]
206+ }
207+ ]
208+ }
209+ ```
210+
211+ ## 2.9 推荐文件命名
212+
213+ 不推荐只用 `baa-result_{tool}_{target}_{status}.md`。
214+ 推荐:
215+
216+ ```text
217+ baa-result_{traceId}_{round}_{blockIndex}_{tool}_{target}_{status}.{ext}
218+ baa-manifest_{traceId}_{round}.json
219+ baa-summary_{traceId}_{round}.md
220+ ```
221+
222+ 示例:
223+
224+ ```text
225+ baa-result_t9ab_r03_b01_exec_conductor_fail.log
226+ baa-result_t9ab_r03_b02_files-read_conductor_ok.md
227+ baa-manifest_t9ab_r03.json
228+ ```
229+
230+ ## 2.10 上传确认回执(upload receipt)
231+
232+ 插件完成页面侧上传后,必须回传确认:
233+
234+ ```json
235+ {
236+ "plan_id": "plan_01JQ...",
237+ "receipts": [
238+ {
239+ "artifact_id": "art_01",
240+ "ok": true,
241+ "remote_handle": "platform-file-123"
242+ },
243+ {
244+ "artifact_id": "art_02",
245+ "ok": true,
246+ "remote_handle": "platform-file-124"
247+ }
248+ ]
249+ }
250+ ```
251+
252+ 只有收到回执,conductor 才能允许发送 `message_text`。
253+
254+ ## 2.11 下载计划(download plan)
255+
256+ 如果浏览器平台返回的是图片 / 文件 / 远程附件,插件也只做下载,不做解释:
257+
258+ ```json
259+ {
260+ "download_plan_id": "dplan_01JQ...",
261+ "items": [
262+ {
263+ "remote_handle": "platform-file-xyz",
264+ "suggested_filename": "generated-city.png",
265+ "save_path": "/tmp/baa/generated-city.png"
266+ }
267+ ]
268+ }
269+ ```
270+
271+ 下载完成后,插件回传本地路径或缓存句柄,由 conductor 再做总结与二次路由。
272+
273+ ## 2.12 结果回注格式(推荐)
274+
275+ ### 文本索引
276+
277+ ```text
278+ [BAA 结果索引]
279+ - instruction_id: inst_01JQ...
280+ - 结果: 失败
281+ - 摘要: pnpm test 完成,2 项失败
282+ - 附件: baa-result_t9ab_r03_b01_exec_conductor_fail.log
283+ - manifest: baa-manifest_t9ab_r03.json
284+ ```
285+
286+ ### 可选 `baa-result` 块
287+
288+ ````text
289+ [BAA 结果索引]
290+
291+ ```baa-result
292+ {
293+ "instruction_id": "inst_01JQ...",
294+ "ok": false,
295+ "summary": "pnpm test 完成,2 项失败。",
296+ "artifact_refs": [
297+ {"artifact_id": "art_01", "filename": "baa-result_t9ab_r03_b01_exec_conductor_fail.log"}
298+ ]
299+ }
300+ ```
301+ ````
302+
303+ ## 2.13 去重键
304+
305+ 推荐:
306+
307+ ```text
308+ dedupe_key = sha256(
309+ platform + "|" +
310+ conversation_id + "|" +
311+ assistant_message_id + "|" +
312+ block_index + "|" +
313+ normalized_block_text
314+ )
315+ ```
316+
317+ ## 2.14 解析器伪代码
318+
319+ ```ts
320+ export function extractBaaBlocks(text: string): string[] {
321+ const blocks: string[] = [];
322+ const re = /```baa\s*
323+([\s\S]*?)```/g;
324+ let m: RegExpExecArray | null;
325+ while ((m = re.exec(text)) !== null) {
326+ const body = m[1]?.trim();
327+ if (body) blocks.push(body);
328+ }
329+ return blocks;
330+ }
331+
332+ export function parseBaaBlock(blockText: string) {
333+ const lines = blockText.split("
334+");
335+ const firstLine = lines[0]?.trim() ?? "";
336+ const m = firstLine.match(/^@([^:\s]+)::([^:\s]+)(?:::([\s\S]*))?$/);
337+ if (!m) return null;
338+
339+ const target = m[1];
340+ const tool = m[2];
341+ const inlineParams = m[3] ? m[3].trim() : null;
342+
343+ if (inlineParams !== null) {
344+ return { target, tool, params: parseParamValue(inlineParams) };
345+ }
346+
347+ const rest = lines.slice(1).join("
348+").trim();
349+ return rest ? { target, tool, params: { command: rest } } : { target, tool, params: {} };
350+ }
351+ ```
1@@ -0,0 +1,171 @@
2+# 03. 路由与能力借用
3+
4+## 3.1 真正的杀手锏不是 exec,而是能力借用
5+
6+如果 BAA 只能做到:
7+
8+```baa
9+@conductor::exec::ls
10+```
11+
12+它只是“能执行本机命令的 AI 插件”。
13+
14+但如果它能做到:
15+
16+```baa
17+@browser.chatgpt::send::请生成一张赛博朋克风格城市夜景图
18+```
19+
20+或者:
21+
22+```baa
23+@pool.image::generate::请生成一张赛博朋克风格城市夜景图
24+```
25+
26+那它就变成了:
27+
28+> **一个 AI 借另一个 AI 或节点的能力来完成自己做不到的事。**
29+
30+## 3.2 路由层级
31+
32+conductor 的路由器建议按以下优先级解析:
33+
34+### Level 1:精确目标
35+- `conductor`
36+- `browser.chatgpt`
37+- `chatgpt.agent.beta`
38+- `node.mini`
39+
40+### Level 2:角色目标
41+- `role.reviewer`
42+- `role.coder`
43+- `role.artist`
44+
45+### Level 3:能力池目标
46+- `pool.image`
47+- `pool.video`
48+- `pool.exec`
49+- `pool.http`
50+- `pool.review`
51+
52+### Level 4:默认回退
53+- 无匹配则回退到人工
54+- 无可用节点则停止自动循环
55+
56+## 3.3 能力声明
57+
58+每个 node / platform / worker 启动时都应该上报:
59+
60+```json
61+{
62+ "node_id": "chatgpt.agent.beta",
63+ "kind": "browser_ai",
64+ "platform": "chatgpt",
65+ "capabilities": [
66+ "chat.send",
67+ "chat.read",
68+ "image.generate",
69+ "code.execute"
70+ ],
71+ "health": "ready",
72+ "policy_tags": ["human_facing", "creative"]
73+}
74+```
75+
76+浏览器插件自己的能力也应显式声明,但只限 transport:
77+
78+```json
79+{
80+ "node_id": "firefox.bridge.local",
81+ "kind": "browser_bridge",
82+ "capabilities": [
83+ "page.request",
84+ "message.observe",
85+ "artifact.upload",
86+ "artifact.download",
87+ "input.inject"
88+ ]
89+}
90+```
91+
92+**注意:插件不声明 `baa.parse`、`artifact.package`、`result.summarize`。**
93+
94+## 3.4 你当前设想的 bootstrap catalog(示例)
95+
96+这是初始经验,不是写死的真理:
97+
98+| 节点 | 示例能力 | 当前缺口 |
99+|---|---|---|
100+| Claude | `http.fetch` `http.post` `code.exec` | `image.generate` `video.generate` |
101+| ChatGPT | `image.generate` `code.exec` | 原生 raw POST 受限 |
102+| Gemini | `image.generate` `video.generate` | 网络请求受限 |
103+| Firefox 插件 | `artifact.upload` `artifact.download` `message.observe` | 不做解析与打包 |
104+
105+## 3.5 推荐 target 设计
106+
107+### 精确调用
108+```baa
109+@chatgpt.agent.beta::send::请生成一张图
110+```
111+
112+### 平台桥接
113+```baa
114+@browser.chatgpt::send::请生成一张图
115+```
116+
117+### 能力池调用
118+```baa
119+@pool.image::generate::请生成一张图
120+```
121+
122+## 3.6 路由打分(建议)
123+
124+```text
125+score =
126+ 40 * capability_match +
127+ 20 * health_score +
128+ 15 * recent_success_score +
129+ 10 * context_affinity +
130+ 10 * policy_fit +
131+ 5 * cost_preference
132+```
133+
134+## 3.7 路由结果对象
135+
136+```json
137+{
138+ "instruction_id": "inst_01JQ...",
139+ "resolved_target": "browser.chatgpt",
140+ "resolved_node_id": "chatgpt.agent.beta",
141+ "route_reason": [
142+ "matched capability image.generate",
143+ "node health ready",
144+ "recent success high"
145+ ],
146+ "fallbacks_considered": ["gemini.agent.gamma"]
147+}
148+```
149+
150+## 3.8 不要做全量 MITM
151+
152+仍然建议:
153+- 页面自己和官方站点通信
154+- 插件只提供页面内 request bridge / upload / download
155+- conductor 做编排、调度、汇总
156+
157+## 3.9 三个能力借用示例
158+
159+### A. Gemini 借本机 shell
160+```baa
161+@conductor::exec::ls /Users/george/code
162+```
163+
164+### B. ChatGPT 借 HTTP / POST 能力
165+```baa
166+@pool.http::request::{"method":"POST","url":"https://api.example.com/data","json":{"key":"value"}}
167+```
168+
169+### C. Claude 借 ChatGPT 生图
170+```baa
171+@browser.chatgpt::send::请生成一张赛博朋克风格的城市夜景图
172+```
1@@ -0,0 +1,153 @@
2+# 04. 执行闭环与状态机
3+
4+## 4.1 为什么必须显式做状态机
5+
6+只要系统进入:
7+
8+AI 回复 → 解析 baa → 执行 → 产物化 → 上传 → 注入索引 → AI 再回复
9+
10+它就已经不是普通插件,而是一个自治循环系统。
11+
12+没有状态机,一定会出现:
13+- 重复执行
14+- streaming 半截误触发
15+- 上传未完成先发送摘要
16+- 多附件并行顺序错乱
17+- bridge 重连后重复回注
18+
19+## 4.2 推荐状态机
20+
21+```mermaid
22+stateDiagram-v2
23+ [*] --> Idle
24+ Idle --> WaitingFinalMessage: assistant streaming
25+ WaitingFinalMessage --> Extracting: final authoritative message ready
26+ Extracting --> Normalizing: found baa blocks
27+ Extracting --> Idle: no baa blocks
28+ Normalizing --> DedupeCheck
29+ DedupeCheck --> PolicyCheck: new instructions
30+ DedupeCheck --> Idle: all duplicate
31+ PolicyCheck --> Dispatching: allowed
32+ PolicyCheck --> Stopped: denied / paused
33+ Dispatching --> WaitingResults
34+ WaitingResults --> MaterializingArtifacts
35+ MaterializingArtifacts --> BuildingManifest
36+ BuildingManifest --> BuildingDeliveryPlan
37+ BuildingDeliveryPlan --> PluginUploading
38+ PluginUploading --> WaitingUploadAck
39+ WaitingUploadAck --> InjectingIndex: all uploads confirmed
40+ WaitingUploadAck --> DeliveryFailed: upload timeout / failed
41+ InjectingIndex --> CoolingDown
42+ CoolingDown --> WaitingFinalMessage: auto-next-turn
43+ CoolingDown --> Idle: stop condition reached
44+ Idle --> Paused: pause
45+ Paused --> Idle: resume
46+ Dispatching --> Draining: drain
47+ WaitingResults --> Draining: drain
48+ Draining --> Idle: inflight finished
49+ DeliveryFailed --> Idle
50+ Stopped --> [*]
51+```
52+
53+## 4.3 可选的下载分支
54+
55+当浏览器侧目标返回的是图片 / 文件 / 附件时:
56+
57+```text
58+Dispatching
59+-> WaitingBrowserArtifacts
60+-> PluginDownloading
61+-> IngestingDownloadedArtifacts
62+-> SummarizingDownloadedArtifacts
63+-> MaterializingArtifacts
64+```
65+
66+这里插件仍然只做下载,不做理解。
67+
68+## 4.4 核心规则
69+
70+1. **只解析最终权威消息**
71+2. **只解析 ` ```baa `**
72+3. **每个 block 独立去重**
73+4. **结果先产物化,再决定怎么交付**
74+5. **上传成功后才能发送索引文本**
75+6. **用户输入优先级最高**
76+
77+## 4.5 推荐闭环流程
78+
79+```text
80+assistant final message ready
81+-> raw message relay to conductor
82+-> extract baa blocks
83+-> parse + normalize
84+-> dedupe
85+-> risk / auth policy
86+-> dispatch in parallel (bounded)
87+-> aggregate raw execution results
88+-> summarize and materialize artifacts
89+-> build manifest
90+-> build delivery plan
91+-> plugin uploads artifacts
92+-> plugin returns receipts
93+-> inject ready-made index text
94+-> send (if auto-send allowed)
95+-> wait next final message
96+```
97+
98+## 4.6 并行与顺序
99+
100+### 并行
101+多个 baa block = 多个独立 instruction = 可并行。
102+
103+### 顺序
104+如果有严格顺序依赖:
105+- 使用单个多行 `exec`
106+- 或分成多轮
107+- 或升级成 task / workflow
108+
109+## 4.7 去重缓存
110+
111+建议保存:
112+- `dedupe_key`
113+- `instruction_id`
114+- `status`
115+- `delivery_plan_id`
116+- `manifest_id`
117+- `upload_receipt_hash`
118+- `executed_at`
119+- `conversation_id`
120+- `assistant_message_id`
121+
122+## 4.8 终止条件
123+
124+满足任一条件应停止自动循环:
125+- hop limit 达到上限(默认 10)
126+- 连续失败达到阈值(默认 3)
127+- 用户手动中断
128+- 系统进入 pause / drain
129+- 下一轮没有 `baa` 指令
130+- 路由器找不到合法目标
131+- artifact 上传持续失败
132+
133+## 4.9 冷却与节流
134+
135+建议默认:
136+- 每轮注入后冷却 1.5 ~ 2 秒
137+- 同轮最大并发数:4 ~ 8
138+- 单轮总上传大小限制:可配置
139+- 结果注入总字符数限制:32KB
140+
141+## 4.10 失败分类
142+
143+最少区分:
144+- `parse_error`
145+- `duplicate_ignored`
146+- `auth_denied`
147+- `route_not_found`
148+- `target_unavailable`
149+- `execution_failed`
150+- `artifact_materialization_failed`
151+- `upload_failed`
152+- `download_failed`
153+- `result_injection_failed`
154+- `loop_aborted_by_human`
1@@ -0,0 +1,155 @@
2+# 05. 权限、治理与安全边界
3+
4+## 5.1 原则
5+自动化不是越开放越好,而是:
6+- 能做事
7+- 不乱做事
8+- 出错能停
9+- 事后可追责
10+
11+## 5.2 风险分层
12+
13+### Tier 0:只读
14+示例:
15+- `describe`
16+- `status`
17+- `current`
18+- `files/read`
19+- `tasks`
20+
21+默认:可自动执行。
22+
23+### Tier 1:低风险写
24+示例:
25+- 工作区内 `files/write`
26+- `browser.*::send`
27+- 创建临时任务
28+- artifact 上传 / 下载
29+
30+默认:可自动执行,但要记录审计。
31+
32+### Tier 2:执行 / 网络 / Git
33+示例:
34+- `exec`
35+- 原始 `request`
36+- `curl` / `POST`
37+- git 写操作
38+
39+默认:建议白名单或 sandbox。
40+
41+### Tier 3:危险 / 破坏性 / 控制面
42+示例:
43+- `rm -rf`
44+- 系统级 reload
45+- pause / drain / credential 操作
46+- 修改非工作区关键文件
47+
48+默认:必须显式放行或人工批准。
49+
50+## 5.3 三道边界
51+
52+### 边界 A:语法边界
53+只执行 ` ```baa `,不执行普通代码块。
54+
55+### 边界 B:权限边界
56+指令解析成功 ≠ 一定允许执行。
57+
58+### 边界 C:环境边界
59+即使允许执行,也要受:
60+- token
61+- sandbox
62+- workspace allowlist
63+- target availability
64+- upload/download size limit
65+限制。
66+
67+## 5.4 插件边界
68+
69+v5 明确要求插件:
70+- 不做 baa 解析
71+- 不做结果总结
72+- 不做大输出提取
73+- 不做 artifact 打包
74+- 不改写 conductor 下发的文本索引
75+
76+这不是性能优化,而是治理边界。
77+
78+## 5.5 host-ops 建议
79+
80+对于本机 host ops:
81+- 继续要求 shared token
82+- 限制可访问目录
83+- 对 `exec` 做 allowlist 或风险扫描
84+- 大输出落日志 / artifact,不直接塞回聊天
85+
86+## 5.6 浏览器凭证边界
87+
88+浏览器平台的 cookies / csrf / session:
89+- 尽量留在页面上下文
90+- 不要把原始凭证吐进日志
91+- conductor 只拿 request / response 摘要与文件句柄
92+
93+## 5.7 审计日志
94+
95+每条指令至少记录:
96+
97+```json
98+{
99+ "instruction_id": "inst_01JQ...",
100+ "source_node": "claude.agent.alpha",
101+ "target": "browser.chatgpt",
102+ "tool": "send",
103+ "risk_tier": "tier1",
104+ "policy_decision": "allowed",
105+ "route_decision": "resolved to chatgpt.agent.beta",
106+ "artifact_manifest_id": "mf_01JQ...",
107+ "delivery_plan_id": "plan_01JQ...",
108+ "started_at": 1774570000000,
109+ "finished_at": 1774570005123,
110+ "approved_by": "policy:auto"
111+}
112+```
113+
114+## 5.8 pause / resume / drain
115+
116+### pause
117+- 暂停接收新一轮自动执行
118+- 可允许当前 in-flight 继续
119+
120+### resume
121+- 恢复自动循环
122+
123+### drain
124+- 不再开始新动作
125+- 等待当前 in-flight 结束后停在安全态
126+
127+## 5.9 结果最小回显
128+
129+不要把以下内容直接注入 AI 会话:
130+- 原始 Authorization header
131+- session cookie
132+- 大段 token
133+- 敏感路径清单
134+- 大量二进制 / base64
135+
136+建议:
137+- 摘要化
138+- 截断
139+- 给 ref / artifact / manifest
140+
141+## 5.10 下载边界
142+
143+浏览器侧远程文件下载也应受策略限制:
144+- 来源平台白名单
145+- 单文件大小上限
146+- 总下载量上限
147+- 文件类型策略
148+- 保存路径限制
149+
150+## 5.11 与“边界、责任、可追责”的长期原则兼容
151+
152+这套设计天然支持:
153+- 最小必要权限
154+- 动态放权
155+- 可暂停 / 回收 / 排空
156+- 谁触发、谁执行、谁上传、谁批准都可追溯
1@@ -0,0 +1,226 @@
2+# 06. 与当前 baa-conductor 的对接建议
3+
4+> 这一节按你当前 repo 的现实结构来写:Firefox 插件、conductor-daemon、本机 host-ops、task/db/auth 都已有骨架,所以重点不是“能不能做”,而是“把职责放对地方”。
5+
6+## 6.1 当前 repo 的现实判断
7+
8+你当前代码骨架里,已经有几层非常关键的东西:
9+
10+### A. 浏览器桥接已经存在
11+- Firefox 插件已有 controller / page bridge / request relay 的骨架
12+- Claude 路线已经是正式入口
13+
14+### B. conductor-daemon 的本地 API 已存在
15+已有入口可承载:
16+- `/v1/browser/claude/open`
17+- `/v1/browser/claude/send`
18+- `/v1/browser/claude/current`
19+- `/v1/exec`
20+- `/v1/files/read`
21+- `/v1/files/write`
22+- `/v1/tasks`
23+- `/v1/system/pause|resume|drain`
24+
25+### C. 更重的系统能力也已有骨架
26+- `packages/db`
27+- `packages/auth`
28+- `apps/worker-runner`
29+- `packages/host-ops`
30+
31+结论:
32+- transport 不需要推倒重来
33+- 真正该补的是 **instruction center + artifact center + delivery planner**
34+
35+## 6.2 v5 的职责重划
36+
37+### 插件只保留这几件事
38+- 页面 request bridge
39+- final authoritative message observation
40+- artifact upload
41+- artifact download
42+- inject prepared text
43+- click send / attach
44+
45+### 从插件剥离出去的事
46+- `extractBaaBlocks`
47+- `parseBaaBlock`
48+- `normalizeInstruction`
49+- `dedupe`
50+- `formatBaaResults`
51+- `summarizeLargeResult`
52+- `buildManifest`
53+- `buildDeliveryPlan`
54+
55+这些全部移入 conductor。
56+
57+## 6.3 建议新增的 conductor 模块
58+
59+```text
60+apps/conductor-daemon/src/instructions/
61+ extract.ts
62+ parse.ts
63+ normalize.ts
64+ dedupe.ts
65+ policy.ts
66+ router.ts
67+ executor.ts
68+ loop.ts
69+
70+apps/conductor-daemon/src/artifacts/
71+ materialize.ts
72+ summarize.ts
73+ package.ts
74+ manifest.ts
75+ delivery-plan.ts
76+ upload-session.ts
77+ download-session.ts
78+ gc.ts
79+```
80+
81+### 职责说明
82+- `materialize.ts`:把 stdout / JSON / diff / image / binary 变成 artifact
83+- `summarize.ts`:产出 AI 可继续使用的摘要
84+- `package.ts`:决定是否生成 summary.md / payload.ext
85+- `manifest.ts`:生成整轮 manifest
86+- `delivery-plan.ts`:把 artifacts + index text 变成插件可执行的 plan
87+- `upload-session.ts`:等待上传回执与重试
88+- `download-session.ts`:管理浏览器侧下载回执
89+
90+## 6.4 插件侧推荐 patch 点
91+
92+### `plugins/baa-firefox/controller.js`
93+保留并增强:
94+- `observeFinalMessageRaw()`
95+- `uploadArtifacts(plan)`
96+- `downloadArtifacts(plan)`
97+- `injectPreparedMessage(text)`
98+- `sendPreparedMessage()`
99+
100+**不要再在这里放 parser / formatter / summarizer。**
101+
102+### `plugins/baa-firefox/page-interceptor.js`
103+继续保留:
104+- 页面内 request bridge
105+- cookie / csrf 留在页面上下文
106+
107+## 6.5 推荐 bridge 消息类型
108+
109+建议在 Firefox WS bridge 上新增以下消息:
110+
111+```text
112+browser.final_message
113+browser.upload_artifacts
114+browser.upload_receipt
115+browser.download_artifacts
116+browser.download_receipt
117+browser.inject_message
118+browser.send_message
119+```
120+
121+### A. final_message
122+插件 -> conductor
123+
124+```json
125+{
126+ "type": "browser.final_message",
127+ "platform": "claude",
128+ "conversation_id": "conv_xxx",
129+ "assistant_message_id": "msg_xxx",
130+ "raw_text": "...assistant final text..."
131+}
132+```
133+
134+### B. upload_artifacts
135+conductor -> 插件
136+
137+```json
138+{
139+ "type": "browser.upload_artifacts",
140+ "plan_id": "plan_01JQ...",
141+ "uploads": [
142+ {
143+ "artifact_id": "art_01",
144+ "filename": "baa-result_t9ab_r03_b01_exec_conductor_fail.log",
145+ "mime_type": "text/plain",
146+ "local_path": "/tmp/baa/art_01.log"
147+ }
148+ ]
149+}
150+```
151+
152+### C. upload_receipt
153+插件 -> conductor
154+
155+```json
156+{
157+ "type": "browser.upload_receipt",
158+ "plan_id": "plan_01JQ...",
159+ "receipts": [
160+ {
161+ "artifact_id": "art_01",
162+ "ok": true,
163+ "remote_handle": "platform-file-123"
164+ }
165+ ]
166+}
167+```
168+
169+## 6.6 为什么这版不再建议“插件 MVP 解析执行”
170+
171+因为一旦你已经决定:
172+- 结果走 artifact
173+- 插件不负责总结 / 提取 / 打包
174+- 未来还要多平台 / 多 AI / 多轮自洽
175+
176+那 parser 与 result formatting 再留在插件里,只会造成分裂的大脑。
177+
178+**v5 的建议是:从第一阶段开始,就让 conductor 成为唯一的大脑。**
179+
180+## 6.7 repo 级别增量文件建议
181+
182+```text
183+docs/design/
184+ baa-instruction-system-v5.md
185+ baa-artifact-delivery.md
186+ baa-loop-state-machine.md
187+
188+apps/conductor-daemon/src/instructions/
189+ extract.ts
190+ parse.ts
191+ normalize.ts
192+ dedupe.ts
193+ policy.ts
194+ router.ts
195+ executor.ts
196+ loop.ts
197+
198+apps/conductor-daemon/src/artifacts/
199+ materialize.ts
200+ summarize.ts
201+ package.ts
202+ manifest.ts
203+ delivery-plan.ts
204+ upload-session.ts
205+ download-session.ts
206+
207+packages/schemas/src/
208+ baa-instruction.ts
209+ baa-result.ts
210+ baa-delivery-plan.ts
211+ baa-artifact-manifest.ts
212+```
213+
214+## 6.8 最小可落地路径
215+
216+1. 插件只做 `final_message raw relay`
217+2. conductor 接收 raw text 后做提取与执行
218+3. conductor 产出 artifacts + manifest + index text
219+4. 插件按 plan 上传
220+5. 插件返回 receipt
221+6. conductor 放行注入文本
222+7. 插件注入并发送
223+
224+这样你就实现了:
225+- 插件很薄
226+- 结果交付稳定
227+- 审计 / 去重 / 重试都在 conductor
1@@ -0,0 +1,125 @@
2+# 07. 渐进式落地阶段
3+
4+## Phase 0:冻结语法,不再反复改格式
5+
6+目标:
7+- 正式确认 v3 语法保留
8+- 正式确认一个块一条指令
9+- 正式确认 `@target::tool::params`
10+
11+验收:
12+- Claude / ChatGPT / Gemini 都能稳定输出 ` ```baa `
13+
14+## Phase 1:把解析中心直接放进 conductor
15+
16+目标:
17+- final message -> conductor extract -> execute -> summary -> inject
18+
19+范围:
20+- `conductor`
21+- `browser.claude`
22+- `exec`
23+- `files/read`
24+- `files/write`
25+- `describe`
26+- `current`
27+- `send`
28+
29+插件只做:
30+- final message relay
31+- inject / send
32+
33+验收:
34+- 稳定自动执行 3~5 轮
35+- 不重复执行
36+- 用户输入能打断
37+- 失败会熔断
38+
39+## Phase 2:artifact 交付与薄插件收口
40+
41+目标:
42+- 结果大于阈值时由 conductor 产物化
43+- 插件只做 upload / download
44+
45+新增:
46+- artifact materializer
47+- summary / manifest builder
48+- delivery plan
49+- upload receipt barrier
50+
51+验收:
52+- 大结果不直接塞进聊天
53+- 上传成功后才发索引文本
54+- 多结果并行时 manifest 稳定
55+
56+## Phase 3:ChatGPT / Gemini 正式浏览器 surface
57+
58+目标:
59+- `browser.chatgpt` / `browser.gemini` 成为正式 target
60+
61+新增:
62+- `/v1/browser/chatgpt/*`
63+- `/v1/browser/gemini/*`
64+- 平台级 capability declaration
65+
66+验收:
67+- Claude 能借 ChatGPT 生图
68+- ChatGPT / Gemini 能借 conductor 做 shell / file / task
69+
70+## Phase 4:能力池与角色池
71+
72+目标:
73+- 从 exact target 扩展到逻辑 target
74+
75+新增:
76+- `pool.image`
77+- `pool.video`
78+- `pool.exec`
79+- `pool.http`
80+- `role.reviewer`
81+- `role.coder`
82+
83+验收:
84+- `@pool.image::generate` 能自动选可用节点
85+- 失败能 fallback
86+
87+## Phase 5:多 AI 自洽协作层接入
88+
89+目标:
90+- round / chain / gossip / consensus 纳入统一编排
91+
92+新增:
93+- `consensus/request`
94+- `chain/start`
95+- `gossip/start`
96+- round_id / branch / lock metadata
97+- 与 `[REQUEST_CONTEXT]` / `[STRESS_TEST]` / `LOCKED` 协同
98+
99+验收:
100+- 能发起一轮受控的三 AI 串行 / gossip 讨论
101+- 结果可审计、可回放、可锁定
102+
103+## Phase 6:任务池与后台长流程
104+
105+目标:
106+- 把复杂动作升级成 task / run
107+
108+新增:
109+- `task/create`
110+- `task/poll`
111+- `task/logs`
112+- artifact refs
113+
114+验收:
115+- 复杂流程不再挤在一个聊天轮次里
116+- AI 只拿摘要 + ref
117+
118+## 每阶段都必须回归
119+
120+- 不解析普通代码块
121+- 不在 streaming 半截执行
122+- 不重复执行同一块
123+- 用户输入能抢占
124+- pause / resume / drain 稳定
125+- 结果不泄露敏感信息
126+- 上传 / 下载失败能重试或降级
1@@ -0,0 +1,138 @@
2+# 08. 直接可用示例
3+
4+ ## 8.1 本机 shell
5+
6+ ```baa
7+ @conductor::exec::ls /Users/george/code
8+ ```
9+
10+ ## 8.2 读取文件
11+
12+ ```baa
13+ @conductor::files/read::{"path":"/Users/george/Desktop/HANDOFF.md"}
14+ ```
15+
16+ ## 8.3 多行 shell
17+
18+ ```baa
19+ @conductor::exec
20+ cd /Users/george/code/baa-conductor
21+ pnpm test
22+ ```
23+
24+ ## 8.4 并行执行
25+
26+ ```baa
27+ @conductor::describe
28+ ```
29+
30+ ```baa
31+ @conductor::files/read::{"path":"/etc/hostname"}
32+ ```
33+
34+ ```baa
35+ @conductor::exec::pwd
36+ ```
37+
38+ ## 8.5 Claude 借 ChatGPT 生图
39+
40+ ```baa
41+ @browser.chatgpt::send::请生成一张赛博朋克风格的城市夜景图
42+ ```
43+
44+ ## 8.6 Gemini 借本机 shell
45+
46+ ```baa
47+ @conductor::exec::ls /Users/george/code
48+ ```
49+
50+ ## 8.7 ChatGPT 借 HTTP 能力
51+
52+ ```baa
53+ @pool.http::request::{"method":"POST","url":"https://api.example.com/data","json":{"key":"value"}}
54+ ```
55+
56+ ## 8.8 能力池形式
57+
58+ ```baa
59+ @pool.image::generate::请生成一张赛博朋克风格的城市夜景图
60+ ```
61+
62+ ## 8.9 精确节点寻址
63+
64+ ```baa
65+ @chatgpt.agent.beta::send::请帮我把下面内容改写成简洁公告:......
66+ ```
67+
68+ ## 8.10 角色路由
69+
70+ ```baa
71+ @role.reviewer::ask::请审阅这份设计,找出最大三个工程风险
72+ ```
73+
74+ ## 8.11 多结果时的索引文本(由 conductor 生成)
75+
76+ ```text
77+ [BAA 结果索引]
78+ - instruction_id: inst_01
79+ - 摘要: 已读取 HANDOFF.md,共 42 行。
80+ - 附件: baa-summary_t9ab_r03.md
81+
82+ - instruction_id: inst_02
83+ - 摘要: pnpm test 完成,2 项失败。
84+ - 附件: baa-result_t9ab_r03_b02_exec_conductor_fail.log
85+ - manifest: baa-manifest_t9ab_r03.json
86+ ```
87+
88+ ## 8.12 `baa-result` 辅助块(可选)
89+
90+ ````text
91+ [BAA 结果索引]
92+
93+ ```baa-result
94+ {
95+ "instruction_id": "inst_02",
96+ "ok": false,
97+ "summary": "pnpm test 完成,2 项失败。",
98+ "artifact_refs": [
99+ {"artifact_id": "art_12", "filename": "baa-result_t9ab_r03_b02_exec_conductor_fail.log"},
100+ {"artifact_id": "mf_03", "filename": "baa-manifest_t9ab_r03.json"}
101+ ]
102+ }
103+ ```
104+ ````
105+
106+ ## 8.13 delivery plan 示例(插件执行,不生成)
107+
108+ ```json
109+ {
110+ "plan_id": "plan_01JQ...",
111+ "uploads": [
112+ {
113+ "artifact_id": "art_12",
114+ "filename": "baa-result_t9ab_r03_b02_exec_conductor_fail.log",
115+ "mime_type": "text/plain",
116+ "local_path": "/tmp/baa/result.log"
117+ }
118+ ],
119+ "message_text": "[BAA 结果索引]
120+- instruction_id: inst_02
121+- 摘要: pnpm test 完成,2 项失败。",
122+ "auto_send": true
123+ }
124+ ```
125+
126+ ## 8.14 upload receipt 示例
127+
128+ ```json
129+ {
130+ "plan_id": "plan_01JQ...",
131+ "receipts": [
132+ {
133+ "artifact_id": "art_12",
134+ "ok": true,
135+ "remote_handle": "platform-file-123"
136+ }
137+ ]
138+ }
139+ ```
1@@ -0,0 +1,128 @@
2+# 09. 结果交付与薄插件专项说明
3+
4+## 9.1 为什么必须把插件变薄
5+
6+一旦你决定:
7+- 结果优先走文件上传
8+- 大结果需要 manifest
9+- 后面还要多平台 / 多 AI / 多轮自动闭环
10+
11+那么如果插件还负责:
12+- 总结
13+- 提取
14+- 打包
15+- 命名
16+- 生成索引文本
17+
18+就会出现两个问题:
19+1. 插件和 conductor 各有一套“半个大脑”
20+2. 多平台时每个插件都要重复实现一遍
21+
22+## 9.2 职责分界表
23+
24+| 组件 | 负责 | 不负责 |
25+|---|---|---|
26+| Firefox / Chrome 插件 | 观察最终消息、上传、下载、注入、发送 | 解析 baa、总结、打包、manifest、命名策略 |
27+| conductor | 提取、解析、去重、策略、执行、总结、artifact、manifest、delivery plan、审计 | 页面 DOM 细节与平台上传实现 |
28+| worker / host-ops | 真正执行动作、产生原始结果 | 决定最终怎么回注聊天 |
29+
30+## 9.3 推荐 artifact 生命周期
31+
32+```text
33+raw execution result
34+-> conductor summarize
35+-> conductor materialize artifacts
36+-> conductor build manifest
37+-> conductor build delivery plan
38+-> plugin upload
39+-> plugin receipt
40+-> conductor finalize index text
41+-> plugin inject/send
42+```
43+
44+## 9.4 为什么需要“索引文本”
45+
46+仅上传附件不够,因为:
47+- AI 不一定立刻知道哪个文件最重要
48+- 多个附件时容易乱
49+- 下一轮 reasoning 需要一个稳定的摘要锚点
50+
51+所以每次都建议有一段固定格式的 `[BAA 结果索引]`。
52+
53+## 9.5 推荐交付模式
54+
55+### 模式 A:inline
56+- 结果很短
57+- 不生成 artifact
58+- 直接发文本
59+
60+### 模式 B:inline + artifact
61+- 结果可简述,但原始载荷较大
62+- 上传 artifact
63+- 发送摘要 + 引用
64+
65+### 模式 C:artifact only
66+- 结果非常大 / 二进制
67+- 只上传 artifact + manifest
68+- 发送极短索引
69+
70+## 9.6 推荐文件类型策略
71+
72+- 日志:`.log`
73+- JSON:`.json`
74+- diff:`.patch`
75+- CSV:`.csv`
76+- 摘要:`.md`
77+- 图片:`.png`
78+- 视频:`.mp4`
79+
80+不建议把所有东西都强制变成 `.md`。
81+
82+## 9.7 上传确认 barrier
83+
84+文件被拖进输入框,不等于平台已经接收成功。
85+必须至少有一种确认机制:
86+- 页面附件 chip 出现并可见
87+- 平台内部上传状态可读
88+- 插件通过已知 DOM / API 确认 attachment ready
89+
90+没有确认前,不发送索引文本。
91+
92+## 9.8 下载流
93+
94+当目标平台生成文件 / 图片 / 视频时:
95+- conductor 先生成 download plan
96+- 插件执行下载
97+- 插件回传本地路径 / handle
98+- conductor 再决定是否:
99+ - 继续摘要
100+ - 转发给其他 AI
101+ - 存档到 artifact store
102+
103+## 9.9 失败与降级
104+
105+### 上传失败
106+- 重试 N 次
107+- 若附件非关键,可降级成短文本摘要
108+- 若附件关键,则停止并提示人工处理
109+
110+### 下载失败
111+- 记录 remote handle
112+- 重试 / 改用页面二次抓取
113+- 仍失败则终止该分支
114+
115+## 9.10 为什么这是长期更省事的路线
116+
117+因为以后无论你接:
118+- Claude
119+- ChatGPT
120+- Gemini
121+- 其他 browser AI
122+
123+插件都只需要实现:
124+- 上传
125+- 下载
126+- 注入
127+- 发送
128+
129+而不会每个平台都重复实现一套 result formatter / artifact packager。
1@@ -0,0 +1,2 @@
2+你可以输出 `baa` 代码块来调用外部能力。一个代码块 = 一条指令。
3+大结果通常会以附件 + `[BAA 结果索引]` 的方式返回,不一定直接回填全文。
1@@ -0,0 +1,2 @@
2+你可以输出 `baa` 代码块来调用外部能力。一个代码块 = 一条指令。
3+大结果通常会以附件 + `[BAA 结果索引]` 的方式返回,不一定直接回填全文。
1@@ -0,0 +1,2 @@
2+你可以输出 `baa` 代码块来调用外部能力。一个代码块 = 一条指令。
3+大结果通常会以附件 + `[BAA 结果索引]` 的方式返回,不一定直接回填全文。
1@@ -0,0 +1,12 @@
2+你可以通过 `baa` 代码块调用 BAA 指令系统。
3+
4+规则:
5+1. 一个 `baa` 代码块只包含一条指令。
6+2. 多条独立指令请写成多个代码块;系统会并行执行。
7+3. 只在你真的需要外部能力时输出 `baa` 代码块。
8+4. 大结果通常不会直接回填全文,而会以:
9+ - `[BAA 结果索引]` 文本
10+ - 附件 / artifact
11+ - 可选 `baa-result` 代码块
12+ 的形式返回。
13+5. 当收到结果索引时,优先依据索引继续推理;需要时再要求读取具体附件。
1@@ -0,0 +1,15 @@
2+# Capability Pool Bootstrap(初始示例)
3+
4+这份表只是 bootstrap,不是永久真理。
5+正式实现仍应以节点自描述与 conductor 路由为准。
6+
7+| target / node | 初始能力 | 备注 |
8+|---|---|---|
9+| `conductor` | `exec` `files/read` `files/write` `tasks` `status` | 本机与编排中心 |
10+| `browser.claude` | `chat.send` `chat.read` | 通过浏览器桥 |
11+| `browser.chatgpt` | `chat.send` `chat.read` `image.generate` | 通过浏览器桥 |
12+| `browser.gemini` | `chat.send` `chat.read` `image.generate` `video.generate` | 通过浏览器桥 |
13+| `pool.exec` | `exec` | 优先路由到 conductor |
14+| `pool.http` | `http.request` | 初期可回落到 conductor |
15+| `pool.image` | `image.generate` | 优先 chatgpt / gemini |
16+| `firefox.bridge.local` | `page.request` `message.observe` `artifact.upload` `artifact.download` `input.inject` | 插件只做 transport |
1@@ -0,0 +1,28 @@
2+# Changelog: v4 -> v5
3+
4+## 新增 / 改动
5+
6+1. 明确插件只负责:
7+ - 最终消息观察
8+ - 上传
9+ - 下载
10+ - 注入 / 发送
11+
12+2. 明确插件不负责:
13+ - baa 提取与解析
14+ - 结果总结
15+ - artifact 打包
16+ - manifest 生成
17+ - delivery plan 生成
18+
19+3. 新增 artifact / manifest / delivery plan / upload receipt / download plan 的正式定义。
20+
21+4. 状态机新增:
22+ - `MaterializingArtifacts`
23+ - `BuildingManifest`
24+ - `BuildingDeliveryPlan`
25+ - `PluginUploading`
26+ - `WaitingUploadAck`
27+
28+5. 将上一版“插件 MVP 解析执行”路线替换为:
29+ **从第一阶段开始就让 conductor 成为唯一解释中心。**
1@@ -0,0 +1,7 @@
2+# Notes
3+
4+1. v5 不推翻 v3 语法。
5+2. v5 也不推翻 v4 的双平面、路由、状态机思路。
6+3. v5 的主要收口点只有一个:
7+ **插件只做 transport / upload / download,结果产物管理全部进入 conductor。**
8+4. 因此如果你要真正落地,优先改的不是 prompt,而是 conductor 的 `instructions/` 与 `artifacts/` 两个目录。
1@@ -0,0 +1,333 @@
2+# 方案:BAA 指令 v3 — 代码块驱动的通用 AI 指令协议
3+
4+日期:2026-03-27
5+来源:George 需求 + Claude/ChatGPT 讨论
6+
7+---
8+
9+## 背景
10+
11+### 指令协议演进
12+
13+| 版本 | 格式 | 问题 |
14+|---|---|---|
15+| v1 | `:: @home.local shell ls` | `::` 容易被渲染引擎吃掉;长对话 AI 忘格式 |
16+| v2 | `@system::shell::{"cmd":"ls"} /@` | AI 能用但格式重;只有 BAA 系统内部走得通 |
17+| v3 | ` ```baa ` 代码块 | 任何 AI 输出代码块就能驱动;不需要原生 function calling |
18+
19+### 核心洞察
20+
21+所有 AI 都会输出代码块。代码块的语言标记已经是一种"这段内容的类型声明"。用 ` ```baa ` 作为"这是一条要执行的指令"的类型声明,天然不会被 Markdown 渲染器吃掉,AI 也很难忘记怎么写代码块。
22+
23+---
24+
25+## 核心规则
26+
27+### 一个代码块 = 一条指令
28+
29+这是最重要的设计决策。一个 baa 代码块只包含一条指令,多条指令用多个代码块表达。
30+
31+好处:
32+- 多个代码块 → 多条指令 → **并行执行**
33+- 语义清晰:一块一事
34+- 和 conductor 的异步模式一致(并行提交 → sleep → 单次 poll)
35+
36+---
37+
38+## 指令格式
39+
40+### 三段式:谁 :: 干什么 :: 怎么干
41+
42+```
43+@target::tool::params
44+```
45+
46+### 单行指令(带参数)
47+
48+ ```baa
49+ @conductor::exec::ls -la /Users/george/code
50+ ```
51+
52+### 单行指令(JSON 参数)
53+
54+ ```baa
55+ @conductor::files/read::{"path": "/Users/george/Desktop/HANDOFF.md"}
56+ ```
57+
58+### 单行指令(无参数)
59+
60+ ```baa
61+ @conductor::describe
62+ ```
63+
64+### 多行参数
65+
66+第一行是 `@target::tool`(没有 `::params`),后续所有行拼接为这一条指令的参数:
67+
68+ ```baa
69+ @conductor::exec
70+ cd /Users/george/code/baa-conductor
71+ git status
72+ git log --oneline -3
73+ ```
74+
75+这是**一条指令**,三行 shell 命令拼成一个多行参数。
76+
77+### 并行执行示例
78+
79+AI 回复中出现 3 个 baa 代码块 = 3 条独立指令 = 并行提交:
80+
81+ 我来同时检查几个东西:
82+
83+ ```baa
84+ @conductor::exec::ls /tmp
85+ ```
86+
87+ ```baa
88+ @conductor::files/read::{"path":"/etc/hostname"}
89+ ```
90+
91+ ```baa
92+ @conductor::describe
93+ ```
94+
95+ 上面三条同时执行,结果出来后我一起分析。
96+
97+代码块之间的普通文本(AI 的思考和解释)被忽略,只提取 baa 块。
98+
99+---
100+
101+## 目标地址(target)
102+
103+| target | 含义 | 路由到 |
104+|---|---|---|
105+| `conductor` | conductor 本机 | conductor local API |
106+| `system` | `conductor` 的别名 | 同上 |
107+| `codex` | codexd 代理 | `/v1/codex/*` |
108+| `browser` | 浏览器代发 | `/v1/browser/request` |
109+| `browser.claude` | Claude 平台 | `/v1/browser/request` platform=claude |
110+| `browser.chatgpt` | ChatGPT 平台 | `/v1/browser/request` platform=chatgpt |
111+| `browser.gemini` | Gemini 平台 | `/v1/browser/request` platform=gemini |
112+
113+### 扩展性
114+
115+target 格式是开放的。未来可以加:
116+- `mac` → SSH 到 Mac 执行
117+- `mini` → 直接在 mini 执行
118+- `racknerd` → VPS 执行
119+- `node.某个节点名` → BAA 网络中的任意节点
120+
121+---
122+
123+## 工具映射(tool → conductor API)
124+
125+| tool | conductor API | 说明 |
126+|---|---|---|
127+| `exec` | `POST /v1/exec` | 执行 shell 命令 |
128+| `files/read` | `POST /v1/files/read` | 读文件 |
129+| `files/write` | `POST /v1/files/write` | 写文件 |
130+| `describe` | `GET /describe` | 系统自描述 |
131+| `describe/business` | `GET /describe/business` | 业务面 |
132+| `describe/control` | `GET /describe/control` | 控制面 |
133+| `status` | `GET /v1/status` | 状态视图 |
134+| `browser/status` | `GET /v1/browser` | 浏览器状态 |
135+| `browser/request` | `POST /v1/browser/request` | 通用代发 |
136+| `browser/actions` | `POST /v1/browser/actions` | 插件管理 |
137+| `codex/sessions` | `POST /v1/codex/sessions` | 创建 codex session |
138+| `codex/turn` | `POST /v1/codex/turn` | 发 codex turn |
139+| `tasks` | `GET /v1/tasks` | 查看任务 |
140+
141+---
142+
143+## 参数解析规则
144+
145+1. `@target::tool`(tool 后面没有 `::` 且后面没有更多行)→ 无参数
146+2. `@target::tool::params`(单行)→ params 以 `{` 开头则 JSON 解析,否则作为字符串
147+3. `@target::tool` 后面有更多行 → 后续行拼接为多行字符串参数
148+
149+---
150+
151+## 解析器
152+
153+### 提取 baa 代码块
154+
155+```javascript
156+function extractBaaBlocks(text) {
157+ const blocks = [];
158+ const re = /```baa\s*\n([\s\S]*?)```/g;
159+ let m;
160+ while ((m = re.exec(text)) !== null) {
161+ const body = m[1].trim();
162+ if (body) blocks.push(body);
163+ }
164+ return blocks;
165+}
166+```
167+
168+### 解析单条指令(单个代码块)
169+
170+```javascript
171+function parseBaaBlock(blockText) {
172+ const lines = blockText.split('\n');
173+ const firstLine = lines[0].trim();
174+
175+ // 第一行必须是 @target::tool 格式
176+ const m = firstLine.match(/^@([^:\s]+)::([^:\s]+)(?:::([\s\S]*))?$/);
177+ if (!m) return null;
178+
179+ const target = m[1];
180+ const tool = m[2];
181+ const inlineParams = m[3] ? m[3].trim() : null;
182+
183+ // 有内联参数 → 单行指令
184+ if (inlineParams !== null) {
185+ return { target, tool, params: parseParamValue(inlineParams) };
186+ }
187+
188+ // 无内联参数 → 后续行是多行参数
189+ const restLines = lines.slice(1);
190+ if (restLines.length === 0 || restLines.every(l => l.trim() === '')) {
191+ return { target, tool, params: {} };
192+ }
193+
194+ return { target, tool, params: { command: restLines.join('\n') } };
195+}
196+
197+function parseParamValue(raw) {
198+ if (!raw) return {};
199+ if (raw.startsWith('{')) {
200+ try { return JSON.parse(raw); } catch { /* fall through */ }
201+ }
202+ return { command: raw };
203+}
204+```
205+
206+### 完整流程
207+
208+```javascript
209+function extractInstructions(aiReplyText) {
210+ return extractBaaBlocks(aiReplyText)
211+ .map(parseBaaBlock)
212+ .filter(inst => inst !== null);
213+}
214+```
215+
216+---
217+
218+## 执行链路
219+
220+### 插件侧解析执行(首版)
221+
222+```
223+AI 回复完成
224+→ 插件提取所有 ```baa 块
225+→ 解析为指令数组
226+→ 并行发给 conductor API(Promise.allSettled)
227+→ 等全部返回
228+→ 拼接结果,一次性注入 AI 对话输入框
229+→ 自动发送
230+→ AI 看到结果继续工作
231+```
232+
233+conductor 侧零改动。
234+
235+### 并行执行
236+
237+```javascript
238+async function executeInstructions(instructions) {
239+ const results = await Promise.allSettled(
240+ instructions.map(inst => routeAndExecute(inst))
241+ );
242+
243+ return results.map((result, i) => {
244+ const inst = instructions[i];
245+ const label = formatInstructionLabel(inst);
246+ if (result.status === 'fulfilled') {
247+ return `--- ${label} ---\n成功:\n${formatOutput(result.value)}`;
248+ } else {
249+ return `--- ${label} ---\n失败: ${result.reason.message}`;
250+ }
251+ }).join('\n\n');
252+}
253+```
254+
255+---
256+
257+## 防死循环
258+
259+AI 回复含 baa 指令 → 执行 → 注入结果 → AI 再回复可能又含 baa 指令 → …
260+
261+### 保护机制
262+
263+1. **最大轮次**:单次对话最多自动执行 N 轮(默认 10)
264+2. **冷却时间**:每轮执行后等 2 秒再注入结果
265+3. **结果标记**:注入文本带 `[BAA 执行结果]` 前缀
266+4. **用户中断**:用户在输入框打字 → 立刻停止自动循环
267+5. **错误熔断**:连续 3 次执行失败 → 自动停止,注入错误摘要
268+
269+---
270+
271+## 结果注入格式
272+
273+并行执行完成后,一次性注入所有结果:
274+
275+```
276+[BAA 执行结果]
277+
278+--- @conductor::exec::ls /tmp ---
279+成功:
280+file1.txt
281+file2.txt
282+
283+--- @conductor::files/read::{"path":"/etc/hostname"} ---
284+成功:
285+mini.local
286+
287+--- @conductor::describe ---
288+成功:
289+{"deployment_mode": "single-node mini", ...}
290+```
291+
292+---
293+
294+## AI 侧提示词
295+
296+只需要在 system prompt 或记忆里写:
297+
298+```
299+你可以通过 baa 代码块执行操作。每个代码块是一条独立指令,多个代码块并行执行:
300+
301+ ```baa
302+ @conductor::exec::shell 命令
303+ ```
304+
305+ ```baa
306+ @conductor::files/read::{"path": "文件路径"}
307+ ```
308+
309+多行 shell 命令:
310+
311+ ```baa
312+ @conductor::exec
313+ cd /some/path
314+ git status
315+ ```
316+
317+执行后结果会自动回传给你。
318+```
319+
320+所有 AI 平台通用(Claude、ChatGPT、Gemini),不需要原生 function calling。
321+
322+---
323+
324+## 实现优先级
325+
326+| 步骤 | 内容 | 改动位置 |
327+|---|---|---|
328+| 1 | 解析器:extractBaaBlocks + parseBaaBlock | controller.js 新增 |
329+| 2 | 执行路由:instruction → conductor API 调用 | controller.js 新增 |
330+| 3 | 并行执行 + 结果拼接 | controller.js 新增 |
331+| 4 | 结果注入 + 自动发送 | controller.js 复用已有 injectText |
332+| 5 | 防死循环保护 | controller.js 新增 |
333+
334+首版全在插件侧(controller.js),conductor 零改动。
1@@ -0,0 +1,56 @@
2+{
3+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4+ "$id": "https://makefile.so/schemas/baa-artifact-manifest.schema.json",
5+ "title": "BAA Artifact Manifest",
6+ "type": "object",
7+ "required": [
8+ "manifest_id",
9+ "trace_id",
10+ "entries"
11+ ],
12+ "properties": {
13+ "manifest_id": {
14+ "type": "string"
15+ },
16+ "trace_id": {
17+ "type": "string"
18+ },
19+ "round_id": {
20+ "type": [
21+ "string",
22+ "null"
23+ ]
24+ },
25+ "entries": {
26+ "type": "array",
27+ "items": {
28+ "type": "object",
29+ "required": [
30+ "instruction_id",
31+ "ok",
32+ "summary",
33+ "artifact_ids"
34+ ],
35+ "properties": {
36+ "instruction_id": {
37+ "type": "string"
38+ },
39+ "ok": {
40+ "type": "boolean"
41+ },
42+ "summary": {
43+ "type": "string"
44+ },
45+ "artifact_ids": {
46+ "type": "array",
47+ "items": {
48+ "type": "string"
49+ }
50+ }
51+ },
52+ "additionalProperties": true
53+ }
54+ }
55+ },
56+ "additionalProperties": true
57+}
1@@ -0,0 +1,65 @@
2+{
3+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4+ "$id": "https://makefile.so/schemas/baa-delivery-plan.schema.json",
5+ "title": "BAA Delivery Plan",
6+ "type": "object",
7+ "required": [
8+ "plan_id",
9+ "trace_id",
10+ "target",
11+ "uploads",
12+ "message_text",
13+ "auto_send"
14+ ],
15+ "properties": {
16+ "plan_id": {
17+ "type": "string"
18+ },
19+ "trace_id": {
20+ "type": "string"
21+ },
22+ "conversation_id": {
23+ "type": [
24+ "string",
25+ "null"
26+ ]
27+ },
28+ "target": {
29+ "type": "string"
30+ },
31+ "uploads": {
32+ "type": "array",
33+ "items": {
34+ "type": "object",
35+ "required": [
36+ "artifact_id",
37+ "filename",
38+ "mime_type",
39+ "local_path"
40+ ],
41+ "properties": {
42+ "artifact_id": {
43+ "type": "string"
44+ },
45+ "filename": {
46+ "type": "string"
47+ },
48+ "mime_type": {
49+ "type": "string"
50+ },
51+ "local_path": {
52+ "type": "string"
53+ }
54+ },
55+ "additionalProperties": true
56+ }
57+ },
58+ "message_text": {
59+ "type": "string"
60+ },
61+ "auto_send": {
62+ "type": "boolean"
63+ }
64+ },
65+ "additionalProperties": true
66+}
1@@ -0,0 +1,106 @@
2+{
3+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4+ "$id": "https://makefile.so/schemas/baa-execution-result.schema.json",
5+ "title": "BAA Execution Result",
6+ "type": "object",
7+ "required": [
8+ "instruction_id",
9+ "target",
10+ "tool",
11+ "ok",
12+ "summary",
13+ "delivery_mode"
14+ ],
15+ "properties": {
16+ "instruction_id": {
17+ "type": "string"
18+ },
19+ "target": {
20+ "type": "string"
21+ },
22+ "tool": {
23+ "type": "string"
24+ },
25+ "ok": {
26+ "type": "boolean"
27+ },
28+ "summary": {
29+ "type": "string"
30+ },
31+ "data": {
32+ "type": [
33+ "object",
34+ "array",
35+ "string",
36+ "number",
37+ "boolean",
38+ "null"
39+ ]
40+ },
41+ "truncated": {
42+ "type": "boolean"
43+ },
44+ "delivery_mode": {
45+ "enum": [
46+ "inline",
47+ "inline_and_artifact",
48+ "artifact_only"
49+ ]
50+ },
51+ "artifact_refs": {
52+ "type": "array",
53+ "items": {
54+ "type": "object",
55+ "required": [
56+ "artifact_id",
57+ "filename",
58+ "mime_type"
59+ ],
60+ "properties": {
61+ "artifact_id": {
62+ "type": "string"
63+ },
64+ "kind": {
65+ "type": "string"
66+ },
67+ "filename": {
68+ "type": "string"
69+ },
70+ "mime_type": {
71+ "type": "string"
72+ },
73+ "size_bytes": {
74+ "type": "integer",
75+ "minimum": 0
76+ },
77+ "sha256": {
78+ "type": [
79+ "string",
80+ "null"
81+ ]
82+ },
83+ "local_path": {
84+ "type": [
85+ "string",
86+ "null"
87+ ]
88+ },
89+ "remote_handle": {
90+ "type": [
91+ "string",
92+ "null"
93+ ]
94+ }
95+ },
96+ "additionalProperties": true
97+ }
98+ },
99+ "error_code": {
100+ "type": [
101+ "string",
102+ "null"
103+ ]
104+ }
105+ },
106+ "additionalProperties": true
107+}
1@@ -0,0 +1,75 @@
2+{
3+ "$schema": "https://json-schema.org/draft/2020-12/schema",
4+ "$id": "https://makefile.so/schemas/baa-instruction-envelope.schema.json",
5+ "title": "BAA Instruction Envelope",
6+ "type": "object",
7+ "required": [
8+ "instruction_id",
9+ "trace_id",
10+ "target",
11+ "tool",
12+ "risk_tier",
13+ "dedupe_key"
14+ ],
15+ "properties": {
16+ "instruction_id": {
17+ "type": "string"
18+ },
19+ "trace_id": {
20+ "type": "string"
21+ },
22+ "conversation_id": {
23+ "type": [
24+ "string",
25+ "null"
26+ ]
27+ },
28+ "assistant_message_id": {
29+ "type": [
30+ "string",
31+ "null"
32+ ]
33+ },
34+ "block_index": {
35+ "type": "integer",
36+ "minimum": 0
37+ },
38+ "source_node": {
39+ "type": "string"
40+ },
41+ "target": {
42+ "type": "string"
43+ },
44+ "tool": {
45+ "type": "string"
46+ },
47+ "params": {
48+ "type": "object"
49+ },
50+ "risk_tier": {
51+ "enum": [
52+ "tier0",
53+ "tier1",
54+ "tier2",
55+ "tier3"
56+ ]
57+ },
58+ "dedupe_key": {
59+ "type": "string"
60+ },
61+ "round_id": {
62+ "type": [
63+ "string",
64+ "null"
65+ ]
66+ },
67+ "hop": {
68+ "type": "integer",
69+ "minimum": 0
70+ },
71+ "created_at": {
72+ "type": "integer"
73+ }
74+ },
75+ "additionalProperties": true
76+}
1@@ -0,0 +1,60 @@
2+{
3+ "nodes": [
4+ {
5+ "node_id": "conductor",
6+ "kind": "orchestrator",
7+ "capabilities": [
8+ "exec",
9+ "files.read",
10+ "files.write",
11+ "tasks.read",
12+ "artifact.package",
13+ "artifact.manifest",
14+ "delivery.plan"
15+ ]
16+ },
17+ {
18+ "node_id": "firefox.bridge.local",
19+ "kind": "browser_bridge",
20+ "capabilities": [
21+ "page.request",
22+ "message.observe",
23+ "artifact.upload",
24+ "artifact.download",
25+ "input.inject"
26+ ]
27+ },
28+ {
29+ "node_id": "chatgpt.agent.beta",
30+ "kind": "browser_ai",
31+ "capabilities": [
32+ "chat.send",
33+ "chat.read",
34+ "image.generate",
35+ "code.execute"
36+ ]
37+ },
38+ {
39+ "node_id": "gemini.agent.gamma",
40+ "kind": "browser_ai",
41+ "capabilities": [
42+ "chat.send",
43+ "chat.read",
44+ "image.generate",
45+ "video.generate"
46+ ]
47+ }
48+ ],
49+ "pools": {
50+ "pool.image": [
51+ "chatgpt.agent.beta",
52+ "gemini.agent.gamma"
53+ ],
54+ "pool.exec": [
55+ "conductor"
56+ ],
57+ "pool.review": [
58+ "chatgpt.agent.beta"
59+ ]
60+ }
61+}