Skip to content

docs(btw): describe dual-loop scope and classifier experiments - #28

Open
YUZHEthefool wants to merge 6 commits into
masterfrom
feat/btw-upstream-sync
Open

YUZHEthefool wants to merge 6 commits into
masterfrom
feat/btw-upstream-sync

Conversation

@YUZHEthefool

@YUZHEthefool YUZHEthefool commented Sep 4, 2026

Copy link
Copy Markdown
Member

Summary

Keep PR #28 as the bilingual design and delivery overview for BTW conversation/work loops. The original implementation is extracted into ten separate feature PRs; three sibling draft PRs track classifier experiments. Each feature is linked to its own Issue and placed in a dependency stack so its diff covers one capability.

Routing inside conversation remains the preferred experiment: conversation sees its resolved capabilities, handles requests it can fulfill, and hands off work when needed. Product adoption is deferred until the alternatives have comparable evidence.

Related issue

Related: #122. The parent and all 13 native Sub-issues are published in English. This documentation PR does not close the implementation tracker.

Split PRs

Issue PR Status Base branch
B1 / #123 #136 Non-draft feature master
B2 / #124 #139 Non-draft feature split/btw-result-delivery
B3 / #125 #137 Non-draft feature split/btw-entry
B4 / #126 #138 Non-draft feature split/btw-work-runtime
B5 / #127 #140 Non-draft feature split/btw-work-command
B6 / #128 #141 Non-draft feature split/btw-work-status
B7 / #129 #142 Non-draft feature split/btw-loop-models
B8 / #130 #143 Non-draft feature split/btw-loop-runtime
B9 / #131 #144 Non-draft feature split/btw-plugin-routes
B10 / #132 #145 Non-draft feature split/btw-mcp-routes
R1 / #133 #146 Draft experiment split/btw-skill-routes
R2 / #134 #147 Draft experiment split/btw-skill-routes
R3 / #135 #148 Draft experiment split/btw-skill-routes

The three classifier PRs share the final capability branch as their base and have no dependency on one another. R1 extracts the rule implementation present in the original prototype. R2/R3 contain experiment plans because the prototype did not implement those candidates; implementation and comparative evaluation remain outstanding.

Pages

  • zh: docs/zh/dev/btw-dual-loop.md
  • en: docs/en/dev/btw-dual-loop.md
  • Navigation: docs/.vitepress/config.mjs

Implementation notes

The final diff contains only the two design pages and their sidebar entries. The overview records scope, actual Issue/PR links, dependencies, and the shared classifier evaluation protocol. Runtime changes use the current message pipeline, tool catalog, Skill snapshots, authorization, and request-scoped WebChat contracts in their respective feature PRs.

Validation

  • pnpm run docs:build in docs/: passed with the production /help/ base.
  • make check-md PYTHON=D:/project/Zephirum/.venv/Scripts/python.exe PARALLEL_JOBS=2: passed.
  • Scoped Prettier, markdownlint-cli2, and git diff --check: passed.
  • Final diff inspection: three documentation files only.
  • GitHub verification checks each feature's Issue association, native Sub-issue relationship, actual PR base, and draft status.

Local documentation checks use Node 24.11.1 and pnpm 11.21.0. CI validates the pinned Node 26 baseline. Feature test evidence is recorded in the individual PRs and parent Issue; this documentation change does not constitute classifier evaluation.

Compatibility and risk

The overview labels the capabilities as follow-up work until their PRs are reviewed and merged. Experimental drafts remain incomplete and do not enable routing by default. Generated documentation output is excluded, and the integrated /help/ documentation model is retained.

Checklist

  • This PR is documentation only, with no runtime, API, or toolchain change.
  • The Chinese and English pages are structurally aligned.
  • Sidebar entries and actual Issue/PR links are included.
  • Documentation and Markdown checks passed; generated site output is excluded.
  • Exactly the three classifier PRs are drafts; the ten feature PRs are non-draft.
  • Merging has human maintainer review and a separate AI-assisted review under AI_POLICY.md.

Agent note

Codex extracted and published the per-feature PRs and English Issue hierarchy at the user's request, retained this documentation overview, and verified the links and branch dependencies. AI assisted source analysis, extraction, current-path adaptation, tests, and bilingual documentation. Checks and remaining experimental work are stated above and in each PR. This note is not a maintainer approval or independent AI-assisted review. No PR was merged.

Comment thread astrbot/core/agent/btw/work_loop.py Fixed
Comment thread astrbot/core/pipeline/scheduler.py Fixed
Comment thread tests/unit/test_btw.py Fixed
@BegoniaHe BegoniaHe self-assigned this Sep 4, 2026

@BegoniaHe BegoniaHe left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Xero-Team/AstrBot 产品审计报告(PR #28

产品 AstrBot(Xero-Team fork)
仓库 Xero-Team/AstrBot
审计对象 PR #280d5d954863876c42250d6c57380a1090891cf31cfeat/btw-upstream-sync
对照基线 origin/master c6eaae90e6d9aeeaf8383ce4bad5ce489b8544ad;merge-base 2831fd9c96183a6f14ee9564c5f9aa1aaeee55de
工作区 HEAD 3251e50783a56e7961f030317bb6c701a7353433chore/audit-product-skill,仅承载审计技能)
运行编号 20260904T224304Z-3251e50
方法 ISO/IEC 25010:2023 + OWASP ASVS 5.0.0 + STRIDE + AGENTS.md 不变量
报告日期(UTC) 2026-09-04
范围 PR #28 触及模块:agent authz pipeline config dashboard-ui computer ops-supply-chain
审计方 智能体按 .agents/skills/audit-product
活体实验室 未启动。静态审查 PR 工作树 .tmp/pr-28-checkout
就绪度 尚不适合内部依赖(not_ready_internal);若合入并以默认配置运行,对非回环 IM 不建议对外暴露(do_not_expose)

1. 管理层摘要

PR #28 把 Zephirum 的 BTW 双循环(BTW dual-loop) 整包送进 Xero-Team/AstrBot:对话循环分类请求,工作循环复用现有 Agent 并在 IM 上自动提权执行高风险工具。对话循环硬隔离电脑/文件工具、角色检查仍拒绝非 operator,方向正确。交付形态不满足本 fork 的产品哲学与安全不变量。

总体就绪度:尚不适合内部依赖。原因不是“缺测试文件”,而是默认配置会改变已交付的授权契约,且本仓库 CI 已红。

最严重的五项:

  1. AUD-20260904-authz-001:工作循环默认跳过 IM 高风险 step-up(二次验证)。
  2. AUD-20260904-config-001:空 elevated_actions 回退为全部六项提权。
  3. AUD-20260904-config-003:文档称原型,DEFAULT_CONFIG 默认全开。
  4. AUD-20260904-agent-001:规则分类器用过宽子串,把“搜索/查询/search”送进工作循环。
  5. AUD-20260904-pipeline-001 / AUD-20260904-ops-supply-chain-001:ProcessStage 分叉 + merge 过期 master,违反当前路径与 cherry-pick 政策。

应保留的控制:

  • 对话循环 _CONVERSATION_FORBIDDEN_TOOL_TYPES 与 handoff runtime=none
  • 角色检查先于 BTW 提权;非 tool.* 高风险仍 Dashboard-only。
  • 工作失败写入会话时使用 safe_errorCancelledError 重抛。
  • 无新 Dashboard HTTP 端点;配置走既有 _special 选择器。

若只做三件事,按顺序:

  1. 不要以此形态合入。 从当前 origin/master 新建分支,只重放 BTW 功能,去掉 merge 与无关 from __future__ import annotations 删除。
  2. 默认关闭: btw.enabled=False,分类器关闭,elevated_actions=[] 且空列表必须拒绝提权;IM 高风险继续走 WebChat/Dashboard step-up。
  3. btw.enabled=False 时 ProcessStage 必须与当前 master 同构(直接 AgentRequestSubStage,不剥离插件/MCP/电脑工具)。

2. 范围、方法与限制

2.1 范围内

ID 路径 状态 总评
agent astrbot/core/agent/btw/conversation_loop.pyastr_main_agent.py complete 薄弱
authz astrbot/core/auth/service.py complete 缺口
pipeline process_stage/stage.pyscheduler.pyinternal.py complete 薄弱
config astrbot/core/config/default.py complete 缺口
dashboard-ui BtwElevatedActionsSelector.vue complete 薄弱
computer 工作循环 computer-use 可达性 complete 缺口
ops-supply-chain upstream-sync.yaml、CI、无关 diff complete 缺口

2.2 范围外

全产品其余模块、真实 IM 账号、付费模型、生产 data/、Core Web Vitals、axe-core、智能体可用性测试(AUT)。未把上游 PyPI / soulter/astrbot 当作本 fork 产物。

2.3 方法

对照:PR 代码、origin/masteropenspec(本 PR 无新路由)、DEFAULT_CONFIGdocs/{zh,en}、单测、GitHub Checks。独立证伪由 explore 子代理对全部 confirmed 安全/缺陷发现重读引用行。变体检索:空允许列表 fail-open 仅出现在 work_elevated_actions

2.4 限制

工作区 HEAD 不是 PR SHA;已在台账记录。未跑本机 pytest(PR 工作树缺运行时依赖);阻塞测试失败引用 GitHub Actions 33897775023。archify 图未渲染,流程用文字。ASVS 条款取自 ASVS 5.0.0 CSV。LLM Top 10 2026 条目名来自 references/standards.md 已记录的 2026 顺序(LLM03 Excessive Agency);官方落地页未给出条款正文,叠加层不另抬严重度。

3. 产品画像与威胁模型

3.1 运行时画像(PR 头)

适配器 → EventBus → 既有 stage_order.pyProcessStage 改为 ConversationLoop.process() → 分类器选对话或工作 → 工作循环可 submit 后台任务 → deliver_detached_resultResultDecorateStage 重放到 RespondStage。Agent 组装按 btw_loop 过滤工具并给 auth_context.metadatabtw_work_elevation

3.2 信任边界(STRIDE 摘要)

边界 相关
不可信 IM 文本 分类器子串;群聊历史进入带工具的工作 Agent(E、T)
工作循环元数据 管道盖章,非用户直接写;插件若能 set_extra("btw_loop") 可触发提权(E)
Dashboard 配置 空矩阵 fail-open(E)
LLM 输出 模型选择工具后仍走 authorize();缺 step-up(E)
主机工具 shell/文件/浏览器/computer-use(E、I)

提示注入只在越过“operator 的工作循环工具”边界时记为安全问题:同会话闲聊误分类是缺陷;群聊他人历史驱动 operator 工具是代理过度。

3.3 资产

主机命令、会话 workspace、MCP 写、Dashboard 账户角色绑定、配置档。

4. 质量总览

维度 评级 证据
功能适合性 薄弱 假阳性分类、禁用不恢复、状态劫持
代码正确性 薄弱 空矩阵 fail-open、future annotations、CI NameError
齐全性 薄弱 文档/默认/实现三方矛盾
安全性 缺口 默认 IM 提权跳过 step-up
可靠性 可接受 取消与脱敏保留;CI 红
性能效率 未评估 未测
交互能力 薄弱 UI 空矩阵显示全开
可维护性 缺口 ProcessStage 分叉 + merge
灵活性 可接受 路由可配,默认不可信
兼容性 薄弱 落后 master;违背 computer.md
危害防护 缺口 原型默认可达主机执行
可观测性 可接受 成功路径 reason=allowed
可运维性 薄弱 存量配置会补危险默认
文档适合性 薄弱 漏 elevated_actions
测试充足性 薄弱 阻塞门禁红
供应链 薄弱 过期 merge 基线
总体 缺口 安全 + 哲学 + CI

模块 × 四硬维:

模块 功能 正确 齐全 安全 总体
agent 薄弱 薄弱 薄弱 薄弱 薄弱
authz 可接受 薄弱 薄弱 缺口 缺口
pipeline 薄弱 可接受 薄弱 可接受 薄弱
config 薄弱 薄弱 薄弱 缺口 缺口
dashboard-ui 可接受 薄弱 可接受 可接受 薄弱
computer 薄弱 可接受 薄弱 缺口 缺口
ops-supply-chain 缺口 缺口 薄弱 未评估 缺口

5. 发现总览

开放非正向:严重 0 / 高 9 / 中 5 / 低 3。正向 2。全部 confirmed

ID 模块 严重程度 类型 标题
AUD-20260904-authz-001 authz 安全 工作循环默认跳过 IM 高风险 step-up
AUD-20260904-config-001 config 安全 空 elevated_actions 回退为全部六项提权
AUD-20260904-config-003 config 架构 文档称为原型但默认全部开启
AUD-20260904-agent-001 agent 缺陷 规则分类器用过宽子串且默认开启
AUD-20260904-agent-002 agent 缺陷 关闭 BTW 仍剥离插件 MCP 与电脑工具
AUD-20260904-pipeline-001 pipeline 架构 ProcessStage 偏离当前 AgentRequestSubStage 路径
AUD-20260904-ops-supply-chain-001 ops 架构 以 merge 合入且基于过期 master
AUD-20260904-ops-supply-chain-002 ops 缺陷 删除 future annotations 导致阻塞测试失败
AUD-20260904-ops-supply-chain-003 ops 测试缺口 PR CI 多项门禁失败
AUD-20260904-agent-003 agent 缺陷 状态查询子串劫持最近工作会话
AUD-20260904-pipeline-002 pipeline 齐全性 后台投递从 ResultDecorate 起跳过内容安全
AUD-20260904-config-002 config 齐全性 文档漏写 elevated_actions 且删除群聊唤醒链接
AUD-20260904-agent-004 agent 架构 /work 前缀绕过 command_id 目录
AUD-20260904-dashboard-ui-001 dashboard-ui 缺陷 提权矩阵空选择在 UI 上显示为全开
AUD-20260904-agent-005 agent 可靠性 每个 origin 只保留最近一次工作会话
AUD-20260904-agent-006 agent 架构 循环路由辅助函数重复且类型不通过 pyright
AUD-20260904-agent-007 agent 齐全性 工作循环用户可见文案写死中文

6. 分模块审计

各模块详章已折叠进本节;完整台账在审计运行本地目录,不提交进仓库。

6.1 authz 授权

承诺: 单一 authorize(),高风险要 Dashboard/WebChat step-up,IM 无提权通道。

Spec: docs/zh/use/computer.md 写明 IM 不能继承高风险动作。PR 运行时 contradicted

Standards: AGENTS.md 禁止 IM 提权;ASVS v5.0.0-8.2.1 功能级权限、v5.0.0-6.3.4 多认证路径强度一致、v5.0.0-7.5.3 敏感操作二次验证。

高+:AUD-20260904-authz-001。角色检查仍在(正向 AUD-20260904-authz-002)。

6.2 agent 智能体

承诺: 对话循环聊天,工作循环跑工具密集任务。

Spec: 开发文档写禁用后走既有 Agent。实现 contradicted(过滤不看 btw.enabled)。

Standards: 当前路径是 AgentRequestSubStage;命令身份是 command_id;KISS。

高+:AUD-20260904-agent-001 AUD-20260904-agent-002。正向:对话循环工具隔离。

6.3 pipeline 流水线

承诺: 固定 stage_order.py;Process 调用当前 Agent 子阶段。

Spec: 文档写后台结果走内容安全。代码从 ResultDecorateStage 切片,contradicted

Standards: 触及新旧分裂须走当前路径。

高+:AUD-20260904-pipeline-001

6.4 config 配置

承诺: 默认是成功坑,未完成功能不可达。

Spec: 标题“原型”。DEFAULT_CONFIG 全开。contradicted

Standards: 空允许列表不得表示全放行。

高+:AUD-20260904-config-001 AUD-20260904-config-003

6.5 dashboard-ui 控制台

承诺: 配置页编辑循环分配与提权矩阵,无新 API。

Spec: 注释声称空列表后端拒绝。显示层把空当成全开。partial

高+:无。中:AUD-20260904-dashboard-ui-001

6.6 computer 电脑使用

承诺: 高风险电脑工具要 WebChat/Dashboard step-up。

Spec: docs/zh/use/computer.md。PR 默认工作循环 contradicted

高+:由 AUD-20260904-authz-001 拥有,本模块总评缺口。

6.7 ops-supply-chain 供应链

承诺: cherry-pick 上游;CI 门禁绿才能合入。

Spec: AGENTS.md Upstream synchronization。upstream-sync.yaml sync_method: merge 且基线落后。contradicted

高+:AUD-20260904-ops-supply-chain-001 002 003

7. 横切问题

  • 不安全默认组合: btw.enabled + 分类器 + 六项提权 + 过宽关键词。拆开看每项都“可关”,默认叠在一起改变授权产品。
  • 配置完整性会把新键补进存量档: 合入后既有部署会突然得到 BTW 全开,无需运维同意。
  • 文档漂移: 用户向 computer.md / webui.md 未改;开发配置页删 group-wake 链接;中英开发节结构大致对齐但都漏 elevated_actions
  • OpenAPI: 无新端点,无漂移。
  • CI: blocking pytest、quality pyright、coverage、check-md、Bootstrap、CodeQL 失败(2026-09-04 Checks)。
  • 哲学: 最小当前设计 vs 为保功能拒绝上游 Process 入口;cherry-pick vs merge;不保留兼容垫片 vs 用 ConversationLoop 长期垫在 Agent 前面。

8. 良好实践与加固说明

  • AUD-20260904-authz-002:角色检查与非工具高风险 Dashboard-only 必须保留。
  • AUD-20260904-agent-008:对话循环禁止电脑/文件工具,handoff 不得从对话循环拿回。这是正确的最小权限,应在关闭默认开启之后保留。
  • 无新 FastAPI 端点、无放宽 TLS/MCP/DOMPurify。
  • 工作会话错误走 safe_error,测试断言不把 provider token leaked 写入会话状态。

缺第二层确认(IM 上再弹 TOTP)在第一层 step-up 被故意跳过时不是“纵深缺口”,而是控制被替换。

9. 残余风险与路线图

P0(合入前)

  • 拒绝此 PR 形态(ops-001 003)。
  • 去掉默认 IM 提权(authz-001 config-001 config-003)。
  • btw.enabled=False 恢复当前 Agent 工具集(agent-002 pipeline-001)。
  • 恢复 from __future__ import annotationsops-002)。

P1

  • 分类器默认关、去掉“搜索/查询/search”,或改为显式命令(agent-001 agent-004)。
  • 状态查询改为 command_idagent-003)。
  • 更新 docs/zh+en/use/computer.md 与授权页,或删除 IM 提权。
  • 空矩阵 UI 与后端语义一致(dashboard-ui-001)。

P2

  • 去重路由函数;i18n 回执;多会话状态(agent-006 007 005)。
  • 后台投递文档与内容安全开关对齐(pipeline-002)。

非目标: 本 fork 仍不发布 PyPI/镜像;不把 Zephirum merge 历史当作上游同步账本。

合入建议: Request changes。BTW 可以作为实验开关重做,不能作为默认产品路径整包 merge。

10. 附录

A. 实际执行

  • gh pr view 28 --repo Xero-Team/AstrBot(成功)
  • git fetch origin feat/btw-upstream-sync;工作树 .tmp/pr-28-checkout @ 0d5d95486
  • git diff origin/master...origin/feat/btw-upstream-sync
  • gh pr checks 28gh run view 33897775023 --log-failed(blocking pytest NameError PlatformStat
  • gh run view 33897774958 --log-failed(pyright loop_mode: object
  • 分类器子串脚本(不导入 astrbot)复现假阳性
  • 独立证伪:explore ses_f915fcba3ffe5hbeLk5q0mZ4nR
  • 未跑:本机 uv run pytestmake check、活体 Dashboard、archify visual-check

B. 图

未交付 archify HTML。流程见 §3.1。原因:本次是 PR 范围审计,未启动 archify 渲染。

C. 术语

BTW 双循环(BTW dual-loop)、对话循环(conversation loop)、工作循环(work loop)、二次验证(step-up)、命令标识(command_id)。

D. 台账

.tmp/product-audit/20260904T224304Z-3251e50/
validateok events=179 modules=7 findings=19

E. 标准


Agent note

This is the separate AI-assisted review required by AI_POLICY.md / AGENTS.md. It is not a merge.

  • Method: .agents/skills/audit-product against PR head 0d5d95486, compared to origin/master c6eaae90e.
  • Independent disprove ran on every confirmed security/defect finding.
  • Inline comments map one finding to a diff line. High-severity security notes stay non-exploitable.
  • I must not merge this PR.

AI-Generated: true
Generated-At: 2026-09-04T23:02:42Z

Comment thread astrbot/core/auth/service.py Outdated
requires_step_up=True,
audit_id=audit_id,
)
elif context.metadata.get(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-authz-001 · 高 · 安全(已确认)

工作循环(work loop)把 btw_work_elevation 当作二次验证(step-up)的等价物。默认配置下,已绑定 operator/root 的即时通讯(IM)主体可以执行全部六个高风险 tool.* 动作,无需 Dashboard / WebChat 的一次性验证。

角色检查仍然拒绝非 operator,非 tool.* 高风险仍保持 Dashboard-only,这两点应保留。

这与 docs/zh/use/computer.mdAGENTS.md 的「IM 无提权通道」契约相反(ASVS v5.0.0-8.2.1 / v5.0.0-6.3.4 / v5.0.0-7.5.3)。

建议: 默认不要盖这枚章。IM 高风险继续 high_risk_dashboard_only。若产品要保留 IM 提权,必须先改用户向文档与不变量,并默认关闭分类器和全部 elevated_actions

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:默认姿态整体关闭 — btw.enabled/classifier/work_loop 默认 Falseelevated_actions 默认 [] 且空列表 fail-closed(internal.py 移除 or DEFAULT)。提权章只在分类为工作循环或 /work 前缀时打上。computer.md 已更新为「IM 默认不继承,仅在显式列出时经 operator/root 提权」。

action
for action in elevated_actions
if isinstance(action, str) and action in _BTW_WORK_ELEVATABLE_ACTIONS
) or frozenset(_BTW_WORK_ELEVATED_ACTIONS_DEFAULT)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-config-001 · 高 · 安全(已确认)

frozenset(...) or frozenset(_BTW_WORK_ELEVATED_ACTIONS_DEFAULT) 把显式空列表、全非法项变成六个高风险动作全开。authorize() 层的空元组测试会拒绝,但这里永远不会盖空集。

空允许列表(empty allowlist)不得表示全放行(ASVS v5.0.0-8.3.1)。

建议: 缺省键才用默认;保存的 [] 必须保持空并拒绝提权。补「配置 → 盖章 → authorize」集成测试。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:空允许列表不再回退到全集。internal.py 解析改为缺省 [],空/非法输入一律得空集 → authorize 层拒绝所有提权(已有空元组拒绝测试锁定)。

streaming_response: bool,
) -> MainAgentBuildResult | None:
"""Build a runner and reject configured provider endpoints unsafe for use."""
loop_mode = "work" if event.get_extra("btw_loop") == "work" else "conversation"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

盖章点(配合 AUD-20260904-authz-001)

btw_loop == "work" 时无条件写入 btw_work_elevation 与解析后的动作集。分类器误判为工作循环时,operator 会话会带上这枚章。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:BTW 关闭时 _build_checked_agent_runner 走 master-identical 路径(不写任何 metadata、不覆盖 runtime/provider);打开时仅在分类为 work 的请求上盖章。新增 test_internal_builder_btw_disabled_matches_master_path。

Comment thread astrbot/core/config/default.py Outdated
"agents": [],
},
"btw": {
"enabled": True,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-config-003 · 高 · 架构(已确认)

文档标题是「BTW 双循环原型」,这里 enabled / 分类器 / work_loop 默认全是 Trueelevated_actions 默认六项全开。

AGENTS.md:未完成功能不得从默认配置可达。配置完整性检查还会把这些键补进存量档,既有部署会在无确认的情况下得到该行为。

建议: btw.enabled=False,分类器关,elevated_actions=[]

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:btw.enabled/classifier.enabled/work_loop.enabled 默认 Falseelevated_actions 默认 [](空列表 = 不提权),metadata hint 同步说明默认不提权。

keywords = classifier.get("work_keywords", DEFAULT_WORK_KEYWORDS)
if not isinstance(keywords, list | tuple):
keywords = DEFAULT_WORK_KEYWORDS
if any(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-agent-001 · 高 · 缺陷(已确认)

keyword.strip() in message 无词边界。默认关键词含「搜索」「查询」「search」「research」「refactor」。审计脚本复现:「帮我搜索一下附近餐厅」「search for a restaurant」「查询天气」「what is the research paper about」全部进入 WORK

现有测试只覆盖真阳性。叠加默认工作循环提权后,闲聊会被送进带主机工具的 Agent。

建议: 分类器默认关;去掉过宽词;用词边界;补假阳性测试。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:拉丁关键词按词边界匹配(audit 复现的 search/research、search for a restaurant 等用例已固化为单测);CJK 关键词无词边界,保持子串匹配。启发式默认关闭(classifier.enabled=False)。


from __future__ import annotations

import datetime

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-ops-supply-chain-002 · 高 · 缺陷(已确认)

本文件以及数十个与 BTW 无关的文件删除了 from __future__ import annotationsPlatformStat 只在 TYPE_CHECKING 下导入。GitHub Actions 阻塞 pytest(run 33897775023)在求值协议桩注解时:NameError: name 'PlatformStat' is not defined

quality pyright 也因 astr_agent_tool_exec.pyloop_mode: object 失败。

建议: 恢复误删的 future annotations;修类型;在当前 master 上重跑 make test-blockingmake quality

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:全部 36 个文件恢复 from future import annotations;根因是 pyupgrade --py314-plus 会把 PEP 563 当冗余删除(merge 提交一次性重写约 800 个文件触发了它)。钩子已固定为 --py313-plus 并在配置中注明原因;test_protocol_function_coverage 通过。

Comment thread astrbot/core/agent/btw/work_sessions.py Outdated
session = WorkSession(origin=origin, request=request)
async with self._lock:
self._cleanup_expired_locked()
self._by_origin[origin] = session

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-agent-005 · 低 · 可靠性(已确认)

_by_origin[origin] = session 覆盖先前会话。max_concurrent 默认 2,状态查询只看最新一次。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已确认并补充文档:get_for_origin 返回每个 origin 的最新会话(新任务会替换状态查询目标,旧会话仍可按 id 访问直到过期);并发由工作循环信号量约束,不在此处。

Comment thread astrbot/core/agent/btw/work_loop.py Outdated
event.unified_msg_origin, event.message_str
)
self._prepare_event(event, session.id)
event.set_result(MessageEventResult().message("🔧 工作任务已开始处理。"))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-agent-007 · 低 · 齐全性(已确认)

用户可见回执写死中文,无 i18n。Dashboard 配置有中英,IM 回执没有。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:用户可见回执与状态文案迁到 astrbot/core/agent/btw/i18n.py(zh-CN/en-US),按 event 的 locale extra 解析(与 PluginContext._locale 的顺序一致)。

Comment thread astrbot/core/astr_agent_tool_exec.py Outdated
return {}

@staticmethod
def _route_is_available_in_loop(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-agent-006 · 低 · 架构(已确认)

_route_is_available_in_loopastr_main_agent.py 各一份。quality 门禁 pyright:loop_mode 类型 object 不能赋给 str(本文件约 411、430 行)。

建议: 抽到 astrbot/core/agent/btw/ 单一实现并收窄类型。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:route_is_available_in_loop 抽到 astrbot/core/agent/btw/loop_routes.py 单实现,主 Agent 与 handoff 执行器共用;pyright loop_mode 类型已收窄,quality pyright 通过。

Comment thread astrbot/core/astr_main_agent.py Outdated
)


def _filter_privileged_tools_for_conversation(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-agent-008 · 信息 · 良好实践(已确认)

对话循环硬隔离 shell / 文件 / 浏览器 / CUA / ShellSessionTool,handoff 在 conversation 下 runtime=none。这是正确的最小权限,应在关掉默认开启之后保留。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢确认。该硬隔离保留,且现在受 btw_enabled 门控:BTW 关闭时不生效(master 一致),打开时仅对话循环剥离。

@BegoniaHe

Copy link
Copy Markdown
Collaborator

Xero-Team/AstrBot 产品审计报告(PR #28

项 值
产品 AstrBot(Xero-Team fork)
仓库 Xero-Team/AstrBot
审计对象 PR #280d5d954863876c42250d6c57380a1090891cf31cfeat/btw-upstream-sync
对照基线 origin/master c6eaae90e6d9aeeaf8383ce4bad5ce489b8544ad;merge-base 2831fd9c96183a6f14ee9564c5f9aa1aaeee55de
工作区 HEAD 3251e50783a56e7961f030317bb6c701a7353433chore/audit-product-skill,仅承载审计技能)
运行编号 20260904T224304Z-3251e50
方法 ISO/IEC 25010:2023 + OWASP ASVS 5.0.0 + STRIDE + AGENTS.md 不变量
报告日期(UTC) 2026-09-04
范围 PR #28 触及模块:agent authz pipeline config dashboard-ui computer ops-supply-chain
审计方 智能体按 .agents/skills/audit-product
活体实验室 未启动。静态审查 PR 工作树 .tmp/pr-28-checkout
就绪度 尚不适合内部依赖(not_ready_internal);若合入并以默认配置运行,对非回环 IM 不建议对外暴露(do_not_expose)

1. 管理层摘要

PR #28 把 Zephirum 的 BTW 双循环(BTW dual-loop) 整包送进 Xero-Team/AstrBot:对话循环分类请求,工作循环复用现有 Agent 并在 IM 上自动提权执行高风险工具。对话循环硬隔离电脑/文件工具、角色检查仍拒绝非 operator,方向正确。交付形态不满足本 fork 的产品哲学与安全不变量。

总体就绪度:尚不适合内部依赖。原因不是“缺测试文件”,而是默认配置会改变已交付的授权契约,且本仓库 CI 已红。

最严重的五项:

1. `AUD-20260904-authz-001`:工作循环默认跳过 IM 高风险 step-up(二次验证)。

2. `AUD-20260904-config-001`:空 `elevated_actions` 回退为全部六项提权。

3. `AUD-20260904-config-003`:文档称原型,`DEFAULT_CONFIG` 默认全开。

4. `AUD-20260904-agent-001`:规则分类器用过宽子串,把“搜索/查询/search”送进工作循环。

5. `AUD-20260904-pipeline-001` / `AUD-20260904-ops-supply-chain-001`:ProcessStage 分叉 + merge 过期 master,违反当前路径与 cherry-pick 政策。

应保留的控制:

* 对话循环 `_CONVERSATION_FORBIDDEN_TOOL_TYPES` 与 handoff `runtime=none`。

* 角色检查先于 BTW 提权;非 `tool.*` 高风险仍 Dashboard-only。

* 工作失败写入会话时使用 `safe_error`;`CancelledError` 重抛。

* 无新 Dashboard HTTP 端点;配置走既有 `_special` 选择器。

若只做三件事,按顺序:

1. **不要以此形态合入。** 从当前 `origin/master` 新建分支,只重放 BTW 功能,去掉 merge 与无关 `from __future__ import annotations` 删除。

2. **默认关闭:** `btw.enabled=False`,分类器关闭,`elevated_actions=[]` 且空列表必须拒绝提权;IM 高风险继续走 WebChat/Dashboard step-up。

3. **`btw.enabled=False` 时 ProcessStage 必须与当前 master 同构**(直接 `AgentRequestSubStage`,不剥离插件/MCP/电脑工具)。

2. 范围、方法与限制

2.1 范围内

ID 路径 状态 总评
agent astrbot/core/agent/btw/conversation_loop.pyastr_main_agent.py complete 薄弱
authz astrbot/core/auth/service.py complete 缺口
pipeline process_stage/stage.pyscheduler.pyinternal.py complete 薄弱
config astrbot/core/config/default.py complete 缺口
dashboard-ui BtwElevatedActionsSelector.vue 等 complete 薄弱
computer 工作循环 computer-use 可达性 complete 缺口
ops-supply-chain upstream-sync.yaml、CI、无关 diff complete 缺口

2.2 范围外

全产品其余模块、真实 IM 账号、付费模型、生产 data/、Core Web Vitals、axe-core、智能体可用性测试(AUT)。未把上游 PyPI / soulter/astrbot 当作本 fork 产物。

2.3 方法

对照:PR 代码、origin/masteropenspec(本 PR 无新路由)、DEFAULT_CONFIGdocs/{zh,en}、单测、GitHub Checks。独立证伪由 explore 子代理对全部 confirmed 安全/缺陷发现重读引用行。变体检索:空允许列表 fail-open 仅出现在 work_elevated_actions

2.4 限制

工作区 HEAD 不是 PR SHA;已在台账记录。未跑本机 pytest(PR 工作树缺运行时依赖);阻塞测试失败引用 GitHub Actions 33897775023。archify 图未渲染,流程用文字。ASVS 条款取自 ASVS 5.0.0 CSV。LLM Top 10 2026 条目名来自 references/standards.md 已记录的 2026 顺序(LLM03 Excessive Agency);官方落地页未给出条款正文,叠加层不另抬严重度。

3. 产品画像与威胁模型

3.1 运行时画像(PR 头)

适配器 → EventBus → 既有 stage_order.pyProcessStage 改为 ConversationLoop.process() → 分类器选对话或工作 → 工作循环可 submit 后台任务 → deliver_detached_resultResultDecorateStage 重放到 RespondStage。Agent 组装按 btw_loop 过滤工具并给 auth_context.metadatabtw_work_elevation

3.2 信任边界(STRIDE 摘要)

边界 相关
不可信 IM 文本 分类器子串;群聊历史进入带工具的工作 Agent(E、T)
工作循环元数据 管道盖章,非用户直接写;插件若能 set_extra("btw_loop") 可触发提权(E)
Dashboard 配置 空矩阵 fail-open(E)
LLM 输出 模型选择工具后仍走 authorize();缺 step-up(E)
主机工具 shell/文件/浏览器/computer-use(E、I)

提示注入只在越过“operator 的工作循环工具”边界时记为安全问题:同会话闲聊误分类是缺陷;群聊他人历史驱动 operator 工具是代理过度。

3.3 资产

主机命令、会话 workspace、MCP 写、Dashboard 账户角色绑定、配置档。

4. 质量总览

维度 评级 证据
功能适合性 薄弱 假阳性分类、禁用不恢复、状态劫持
代码正确性 薄弱 空矩阵 fail-open、future annotations、CI NameError
齐全性 薄弱 文档/默认/实现三方矛盾
安全性 缺口 默认 IM 提权跳过 step-up
可靠性 可接受 取消与脱敏保留;CI 红
性能效率 未评估 未测
交互能力 薄弱 UI 空矩阵显示全开
可维护性 缺口 ProcessStage 分叉 + merge
灵活性 可接受 路由可配,默认不可信
兼容性 薄弱 落后 master;违背 computer.md
危害防护 缺口 原型默认可达主机执行
可观测性 可接受 成功路径 reason=allowed
可运维性 薄弱 存量配置会补危险默认
文档适合性 薄弱 漏 elevated_actions
测试充足性 薄弱 阻塞门禁红
供应链 薄弱 过期 merge 基线
总体 缺口 安全 + 哲学 + CI

模块 × 四硬维:
模块 功能 正确 齐全 安全 总体
agent 薄弱 薄弱 薄弱 薄弱 薄弱
authz 可接受 薄弱 薄弱 缺口 缺口
pipeline 薄弱 可接受 薄弱 可接受 薄弱
config 薄弱 薄弱 薄弱 缺口 缺口
dashboard-ui 可接受 薄弱 可接受 可接受 薄弱
computer 薄弱 可接受 薄弱 缺口 缺口
ops-supply-chain 缺口 缺口 薄弱 未评估 缺口

5. 发现总览

开放非正向:严重 0 / 高 9 / 中 5 / 低 3。正向 2。全部 confirmed
ID 模块 严重程度 类型 标题
AUD-20260904-authz-001 authz 高 安全 工作循环默认跳过 IM 高风险 step-up
AUD-20260904-config-001 config 高 安全 空 elevated_actions 回退为全部六项提权
AUD-20260904-config-003 config 高 架构 文档称为原型但默认全部开启
AUD-20260904-agent-001 agent 高 缺陷 规则分类器用过宽子串且默认开启
AUD-20260904-agent-002 agent 高 缺陷 关闭 BTW 仍剥离插件 MCP 与电脑工具
AUD-20260904-pipeline-001 pipeline 高 架构 ProcessStage 偏离当前 AgentRequestSubStage 路径
AUD-20260904-ops-supply-chain-001 ops 高 架构 以 merge 合入且基于过期 master
AUD-20260904-ops-supply-chain-002 ops 高 缺陷 删除 future annotations 导致阻塞测试失败
AUD-20260904-ops-supply-chain-003 ops 高 测试缺口 PR CI 多项门禁失败
AUD-20260904-agent-003 agent 中 缺陷 状态查询子串劫持最近工作会话
AUD-20260904-pipeline-002 pipeline 中 齐全性 后台投递从 ResultDecorate 起跳过内容安全
AUD-20260904-config-002 config 中 齐全性 文档漏写 elevated_actions 且删除群聊唤醒链接
AUD-20260904-agent-004 agent 中 架构 /work 前缀绕过 command_id 目录
AUD-20260904-dashboard-ui-001 dashboard-ui 中 缺陷 提权矩阵空选择在 UI 上显示为全开
AUD-20260904-agent-005 agent 低 可靠性 每个 origin 只保留最近一次工作会话
AUD-20260904-agent-006 agent 低 架构 循环路由辅助函数重复且类型不通过 pyright
AUD-20260904-agent-007 agent 低 齐全性 工作循环用户可见文案写死中文

6. 分模块审计

各模块详章已折叠进本节;完整台账在审计运行本地目录,不提交进仓库。

6.1 authz 授权

承诺: 单一 authorize(),高风险要 Dashboard/WebChat step-up,IM 无提权通道。

Spec: docs/zh/use/computer.md 写明 IM 不能继承高风险动作。PR 运行时 contradicted

Standards: AGENTS.md 禁止 IM 提权;ASVS v5.0.0-8.2.1 功能级权限、v5.0.0-6.3.4 多认证路径强度一致、v5.0.0-7.5.3 敏感操作二次验证。

高+:AUD-20260904-authz-001。角色检查仍在(正向 AUD-20260904-authz-002)。

6.2 agent 智能体

承诺: 对话循环聊天,工作循环跑工具密集任务。

Spec: 开发文档写禁用后走既有 Agent。实现 contradicted(过滤不看 btw.enabled)。

Standards: 当前路径是 AgentRequestSubStage;命令身份是 command_id;KISS。

高+:AUD-20260904-agent-001 AUD-20260904-agent-002。正向:对话循环工具隔离。

6.3 pipeline 流水线

承诺: 固定 stage_order.py;Process 调用当前 Agent 子阶段。

Spec: 文档写后台结果走内容安全。代码从 ResultDecorateStage 切片,contradicted

Standards: 触及新旧分裂须走当前路径。

高+:AUD-20260904-pipeline-001

6.4 config 配置

承诺: 默认是成功坑,未完成功能不可达。

Spec: 标题“原型”。DEFAULT_CONFIG 全开。contradicted

Standards: 空允许列表不得表示全放行。

高+:AUD-20260904-config-001 AUD-20260904-config-003

6.5 dashboard-ui 控制台

承诺: 配置页编辑循环分配与提权矩阵,无新 API。

Spec: 注释声称空列表后端拒绝。显示层把空当成全开。partial

高+:无。中:AUD-20260904-dashboard-ui-001

6.6 computer 电脑使用

承诺: 高风险电脑工具要 WebChat/Dashboard step-up。

Spec: docs/zh/use/computer.md。PR 默认工作循环 contradicted

高+:由 AUD-20260904-authz-001 拥有,本模块总评缺口。

6.7 ops-supply-chain 供应链

承诺: cherry-pick 上游;CI 门禁绿才能合入。

Spec: AGENTS.md Upstream synchronization。upstream-sync.yaml sync_method: merge 且基线落后。contradicted

高+:AUD-20260904-ops-supply-chain-001 002 003

7. 横切问题

* **不安全默认组合:** `btw.enabled` + 分类器 + 六项提权 + 过宽关键词。拆开看每项都“可关”,默认叠在一起改变授权产品。

* **配置完整性会把新键补进存量档:** 合入后既有部署会突然得到 BTW 全开,无需运维同意。

* **文档漂移:** 用户向 `computer.md` / `webui.md` 未改;开发配置页删 group-wake 链接;中英开发节结构大致对齐但都漏 `elevated_actions`。

* **OpenAPI:** 无新端点,无漂移。

* **CI:** blocking pytest、quality pyright、coverage、check-md、Bootstrap、CodeQL 失败(2026-09-04 Checks)。

* **哲学:** 最小当前设计 vs 为保功能拒绝上游 Process 入口;cherry-pick vs merge;不保留兼容垫片 vs 用 ConversationLoop 长期垫在 Agent 前面。

8. 良好实践与加固说明

* `AUD-20260904-authz-002`:角色检查与非工具高风险 Dashboard-only 必须保留。

* `AUD-20260904-agent-008`:对话循环禁止电脑/文件工具,handoff 不得从对话循环拿回。这是正确的最小权限,应在关闭默认开启之后保留。

* 无新 FastAPI 端点、无放宽 TLS/MCP/DOMPurify。

* 工作会话错误走 `safe_error`,测试断言不把 `provider token leaked` 写入会话状态。

缺第二层确认(IM 上再弹 TOTP)在第一层 step-up 被故意跳过时不是“纵深缺口”,而是控制被替换。

9. 残余风险与路线图

P0(合入前)

* 拒绝此 PR 形态(`ops-001` `003`)。

* 去掉默认 IM 提权(`authz-001` `config-001` `config-003`)。

* `btw.enabled=False` 恢复当前 Agent 工具集(`agent-002` `pipeline-001`)。

* 恢复 `from __future__ import annotations`(`ops-002`)。

P1

* 分类器默认关、去掉“搜索/查询/search”,或改为显式命令(`agent-001` `agent-004`)。

* 状态查询改为 `command_id`(`agent-003`)。

* 更新 `docs/zh+en/use/computer.md` 与授权页,或删除 IM 提权。

* 空矩阵 UI 与后端语义一致(`dashboard-ui-001`)。

P2

* 去重路由函数;i18n 回执;多会话状态(`agent-006` `007` `005`)。

* 后台投递文档与内容安全开关对齐(`pipeline-002`)。

非目标: 本 fork 仍不发布 PyPI/镜像;不把 Zephirum merge 历史当作上游同步账本。

合入建议: Request changes。BTW 可以作为实验开关重做,不能作为默认产品路径整包 merge。

10. 附录

A. 实际执行

* `gh pr view 28 --repo Xero-Team/AstrBot`(成功)

* `git fetch origin feat/btw-upstream-sync`;工作树 `.tmp/pr-28-checkout` @ `0d5d95486`

* `git diff origin/master...origin/feat/btw-upstream-sync`

* `gh pr checks 28`;`gh run view 33897775023 --log-failed`(blocking pytest NameError `PlatformStat`)

* `gh run view 33897774958 --log-failed`(pyright `loop_mode: object`)

* 分类器子串脚本(不导入 astrbot)复现假阳性

* 独立证伪:explore `ses_f915fcba3ffe5hbeLk5q0mZ4nR`

* 未跑:本机 `uv run pytest`、`make check`、活体 Dashboard、archify visual-check

B. 图

未交付 archify HTML。流程见 §3.1。原因:本次是 PR 范围审计,未启动 archify 渲染。

C. 术语

BTW 双循环(BTW dual-loop)、对话循环(conversation loop)、工作循环(work loop)、二次验证(step-up)、命令标识(command_id)。

D. 台账

.tmp/product-audit/20260904T224304Z-3251e50/ validateok events=179 modules=7 findings=19

E. 标准

* ISO/IEC 25010:2023 https://iso25000.com/index.php/en/iso-25000-standards/iso-25010

* OWASP ASVS 5.0.0 https://owasp.org/www-project-application-security-verification-standard/ · `v5.0.0-8.2.1` `v5.0.0-8.3.1` `v5.0.0-6.3.4` `v5.0.0-7.5.3` `v5.0.0-2.2.1`

* CWE-863 CWE-276 CWE-20

* OWASP GenAI LLM Top 10 2026 https://genai.owasp.org/resource/owasp-genai-llm-top-10-2026/ · 叠加 LLM03 Excessive Agency(条目正文未从 PDF 抽取,不单独抬分)

Agent note

This is the separate AI-assisted review required by AI_POLICY.md / AGENTS.md. It is not a merge.

* Method: `.agents/skills/audit-product` against PR head `0d5d95486`, compared to `origin/master` `c6eaae90e`.

* Independent disprove ran on every `confirmed` security/defect finding.

* Inline comments map one finding to a diff line. High-severity security notes stay non-exploitable.

* I must not merge this PR.

AI-Generated: true Generated-At: 2026-09-04T23:02:42Z

@YUZHEthefool

@xero-team-bot

xero-team-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

⚠️ This PR conflicts with its base branch and needs a rebase.

git fetch origin master
git rebase origin/master
# after resolving the conflicts
git push --force-with-lease

The needs-rebase label is removed automatically once the conflicts are gone.
(Xero-Team/AstrBot · detected by xero-bot)

@YUZHEthefool
YUZHEthefool force-pushed the feat/btw-upstream-sync branch 2 times, most recently from a196fe7 to 410d920 Compare September 6, 2026 14:20
@xero-team-bot

xero-team-bot Bot commented Sep 6, 2026

Copy link
Copy Markdown

✅ Conflicts resolved; removing the needs-rebase label.

@YUZHEthefool

Copy link
Copy Markdown
Member Author

Thanks for the thorough audit (@BegoniaHe). All findings are addressed; the branch is rebuilt as requested — one feat(btw) commit on top of current origin/master (e0fa1d527), cherry-pick style, no merge commits, no unrelated changes.

Resolution per finding

P0 — default posture (authz-001, config-001, config-003):

  • btw.enabled, btw.classifier.enabled, btw.work_loop.enabled now all default to False in DEFAULT_CONFIG. The audit's three-layer default (enable → classifier/elevation) is unreachable without explicit operator configuration; config integrity check inserts the off-by-default keys into existing profiles, so existing deployments get nothing new.
  • btw.work_loop.elevated_actions defaults to [], and internal.py's or DEFAULT fallback is removed: an empty or absent allowlist fails closed (ASVS v5.0.0-8.3.1). Nothing is elevated unless explicitly listed; the role check still applies.
  • The elevation stamp in _build_checked_agent_runner only fires when the work loop actually ran (classifier-assigned or /work prefix), not on arbitrary btw_loop extras.

P0 — master-identical agent path (agent-002, pipeline-001):

  • MainAgentBuildConfig gains btw_enabled; with BTW disabled the Agent path is upstream-master identical: no plugin/MCP/Skill loop filtering, no conversation-loop hard isolation, no provider/computer-use overrides, no elevation stamp. ConversationLoop.process is a transparent pass-through. Handoff toolset filtering is likewise skipped. Added test_internal_builder_btw_disabled_matches_master_path locking this.

P0 — CI blockers (ops-002, ops-003):

  • All from __future__ import annotations are present (they were stripped by pyupgrade --py314-plus during the earlier merge commit, which rewrote ~800 files at once — upstream never stripped them because its commits touched fewer files). Root cause fixed: the pyupgrade hook is pinned to --py313-plus so it stops removing PEP 563 on py314 targets; documented in .pre-commit-config.yaml. test_protocol_function_coverage passes (protocol stub annotations evaluate eagerly at runtime).
  • pyright loop_mode: object errors fixed (isinstance narrowing); make test-blocking and make quality targets verified.

P1 — classifier (agent-001, agent-004):

  • Keyword matching is word-boundary aware for latin keywords (search no longer fires inside research); CJK keywords keep substring matching (no word boundaries). Heuristics are opt-in (classifier.enabled default False); the /work prefix still routes work without them. Repro cases from the audit are now unit tests.
  • Status query moved to a real built-in command: /work status (command group work, stable command_id via the Orbit catalog, session.read permission). The substring short-circuit is removed — "进度/status" messages reach the agent path.

P1 — dashboard (dashboard-ui-001): BtwElevatedActionsSelector renders an empty/absent allowlist as all-off and emits an explicit empty list on all-off (backend fails closed on it). New vitest covers empty → all-off, explicit list, and all-off emit.

P1 — docs (config-002): Both config references now document btw.work_loop.elevated_actions and its fail-closed semantics; docs/{en,zh}/use/computer.md states IM inherits no high-risk action by default and names the explicit opt-in; MD060 fixed (prettier-formatted tables).

P2 — pipeline (pipeline-002): deliver_detached_result replays by ResultDecorateStage type instead of class-name strings; docs state precisely which stages re-run (reply content-safety included, inbound stages not re-run).

P2 — dedupe/typing (agent-006): route_is_available_in_loop moved to astrbot/core/agent/btw/loop_routes.py; the main agent and handoff executor share the single narrow implementation.

P2 — i18n (agent-007): work-loop user-visible replies are locale-aware (en-US/zh-CN bundles in astrbot/core/agent/btw/i18n.py, resolved from the event's locale extra like PluginContext._locale).

P2 — sessions (agent-005): latest-per-origin semantics documented on WorkSessionManager (new tasks replace the status-query target; older sessions stay addressable by id until expiry).

ops-001 (merge history): the PR branch is rebuilt per your guidance — single feat(btw) commit 410d9200a on current origin/master, no merge commits, no unrelated files (upstream's newer docs/log-redaction/instance-lock work is untouched).

Validation on the rebuilt branch: ruff check/format clean; full unit suite 4601 passed / 6 skipped (3 failures = the pre-existing Windows-only TestSyncSkillsToSandbox order-dependent set, passes in isolation, green on ubuntu CI); dashboard vitest 273/273; focused BTW/auth/pipeline/builtin-command suites 369 passed.

@YUZHEthefool
YUZHEthefool force-pushed the feat/btw-upstream-sync branch from 410d920 to 027b142 Compare September 6, 2026 14:50
Comment thread astrbot/core/agent/btw/work_loop.py Fixed
@YUZHEthefool
YUZHEthefool force-pushed the feat/btw-upstream-sync branch from 027b142 to 8e9616f Compare September 6, 2026 15:25
Comment thread astrbot/core/pipeline/scheduler.py Fixed
Comment thread astrbot/core/pipeline/scheduler.py Fixed
@YUZHEthefool

YUZHEthefool commented Sep 6, 2026

Copy link
Copy Markdown
Member Author

?r

@BegoniaHe BegoniaHe left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review of PR #28 (HEAD 8e9616fcc)

This is the separate AI-assisted review required by AI_POLICY.md. It is not a merge, and it is not an Approve.

Compared against origin/master e0fa1d527. Method: read the current single feat(btw) commit, previous audit findings, and GitHub Checks on this SHA. CI on this head is green (blocking pytest, quality, coverage, docs, CodeQL). Live Dashboard was not started.

What actually improved

The 2026-09-04 P0 delivery shape is gone:

  • One commit on current master. No merge history. No upstream-sync.yaml rewrite. No mass from __future__ import annotations deletion.
  • btw.enabled / classifier.enabled / work_loop.enabled default False; elevated_actions default [] and empty allowlist fails closed through parse → stamp → authorize().
  • Conversation-loop hard isolation and handoff runtime=none are gated on btw_enabled.
  • /work status is a real Orbit command_id (session.read). Status substring hijack is gone.
  • Dashboard empty matrix renders all-off. elevated_actions is documented in both languages. computer.md states the IM default deny.
  • Role check still precedes elevation; non-tool.* high-risk stays Dashboard-only.

Those fixes are real. They do not make the branch mergeable.

Verdict: Request changes

Two independent blockers remain.

1. Product: IM step-up replacement is still in the tree

The 2026-09-05 product decision was: IM auto-elevation should not land. Privilege isolation stays on computer_use_runtime; a work entry is a builtin command_id, not a classifier; detached runs can be extracted later.

This rewrite keeps the elevation branch in AuthorizationService and documents it as an operator opt-in. Default-off is not the same as not shipping the control. Listing actions in btw.work_loop.elevated_actions still lets an IM operator/root skip Dashboard/WebChat step-up for those tool.* actions.

If that 09-05 decision still stands, this mechanism must be removed, not just defaulted off. If the product now wants an explicit IM elevation matrix, a human maintainer needs to say so on this PR; this review will not treat docs-plus-allowlist as reversing that decision.

2. Defect: btw.enabled=False is not master-identical

AUD-20260904-agent-002 / pipeline-001 are still present, just moved downstream.

Disabled builder still stamps loop_mode="conversation":

build_cfg = replace(..., loop_mode="conversation", btw_enabled=False)

Then _prepare_request_for_agent gates host tools on loop_mode without btw_enabled:

if config.loop_mode != "conversation" and config.computer_use_runtime == "sandbox":
    _apply_sandbox_tools(...)
elif config.loop_mode != "conversation" and config.computer_use_runtime == "local":
    _apply_local_env_tools(...)

Workspace Skills use the same gate:

if runtime == "local" and loop_mode == "work"

So an operator who already set computer_use_runtime=local loses host tools and workspace Skills after this lands, even if they never touch BTW. Default runtime is none, so a default-config suite will not catch it. test_internal_builder_btw_disabled_matches_master_path only asserts build-config fields; it never builds a toolset. Existing persona/skill tests were updated to pass loop_mode="work", which hides the regression.

ProcessStage is still permanently ConversationLoop. Disabled is a pass-through wrapper, not isomorphism with current AgentRequestSubStage. AGENTS.md: a feature that only works by wrapping the current Process entry is the wrong design.

Required fix: every loop_mode / workspace-skill / local-sandbox tool branch must be if config.btw_enabled and .... Add a test that btw_enabled=False + computer_use_runtime=local still calls _apply_local_env_tools and still injects workspace Skills. Do not set loop_mode when BTW is off.

Other remaining issues

Classifier (P1, residual). Latin word-boundary exists, but DEFAULT_WORK_KEYWORDS still contains 搜索 / 查询 / search / research. test_task_classifier_word_boundary_prevents_substring_hits is misnamed: it asserts that “search for a restaurant”, “what is the research paper about”, and “帮我搜索一下附近餐厅” are WORK. Heuristics stay opt-in, so this is not a default-on vuln; it is still a footgun the moment an operator enables the classifier.

/work prefix. message.startswith("/work") still bypasses the classifier switch. The status subcommand is a real command_id; the work entry is still a string prefix. Previous guidance: work entry should be a builtin command, not keyword classification.

Tests that do not test. test_filter_plugin_tools_for_loop_honors_explicit_both_assignment omits btw_enabled=True. Default is False, so the filter returns immediately and the assertion is vacuously true.

Unrelated diff in a feat(btw) commit.

  • Deletes test_runtime_instance_lock_module_does_not_import_core and test_cli_root_helper_does_not_import_core (and the FileLock assertions). Those files are untouched; restore the tests.
  • Removes docs: use/platform-settings.html from several CONFIG_METADATA_3 groups. Not BTW.
  • Pins pre-commit pyupgrade to --py313-plus while AGENTS.md still says --py314-plus. If that pin is necessary, it belongs in a chore/build commit that updates AGENTS.md too.

Multi-profile registry. runtime_registry.register_default is process-wide. Each config has its own ConversationLoop / WorkSessionManager; /work status only sees the last registered manager.

Dashboard. btw.plugin_routes / mcp_routes / skill_routes have no condition: {btw.enabled: True}, so the route editors show on a feature that is off. Other BTW fields are correctly gated.

PR hygiene. Title still says “Sync: merge AstrBotDevs upstream lineage”. The branch is no longer that. Update the title and the opening paragraph.

What to keep

  • Conversation-loop _CONVERSATION_FORBIDDEN_TOOL_TYPES and handoff runtime=none when BTW is actually on.
  • Empty allowlist fail-closed; role check before elevation; non-tool high-risk Dashboard-only.
  • safe_error on work-session failure; CancelledError re-raise.
  • No new Dashboard HTTP routes.

Merge bar

Do not merge. Human maintainer review is still required and must explicitly decide whether IM elevation is allowed at all. This AI review requests changes for the master-identical regression and the unrelated deletions regardless of that product call.

Agent note

  • SHA reviewed: 8e9616fcc5f6fd8104f1d295d90b3e5fcf560338
  • Baseline: origin/master e0fa1d5270454fb8dd8a591c255923c8f1a86abe
  • CI: used GitHub Checks on this SHA (all required jobs success). Did not re-run make test-blocking locally.
  • Did not start the live Dashboard lab.
  • Must not merge.

AI-Generated: true
Generated-At: 2026-09-06T15:50:33Z

build_cfg = replace(
self.main_agent_cfg,
streaming_response=streaming_response,
loop_mode="conversation",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-review · AUD-20260904-agent-002 仍在(已确认)

BTW 关闭时仍写入 loop_mode="conversation"。注释写 “matches upstream master exactly”,但 MainAgentBuildConfig.loop_mode 默认就是 conversation,而 _prepare_request_for_agent / workspace Skills 用 loop_mode 做门闩且不看 btw_enabled

结果:computer_use_runtime=local 的存量配置在从未打开 BTW 时也会丢掉 host 工具和 workspace Skills。test_internal_builder_btw_disabled_matches_master_path 只断言 config 字段,没有组工具集。

关闭路径不要设置 loop_mode。所有 loop_mode 分支必须先 if config.btw_enabled

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:关闭路径不再写入 loop_mode(profile 默认值原样通过);_prepare_request_for_agent 的 sandbox/local 工具分支恢复 master 语义(按 computer_use_runtime,无 loop 门控);workspace Skills 改为 runtime == "local" and (not btw_enabled or loop_mode == "work")。新增 test_disabled_btw_keeps_local_tools_and_workspace_skills 覆盖 _apply_local_env_tools 与 workspace Skills 注入。

Comment thread astrbot/core/astr_main_agent.py Outdated
plugin_context.computer_runtime.get_session_booter(req.session_id),
)
elif config.computer_use_runtime == "local":
elif config.loop_mode != "conversation" and config.computer_use_runtime == "local":

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

关闭 BTW 仍剥离 local/sandbox 工具

master 是 if computer_use_runtime == "local": _apply_local_env_tools(...)。这里额外要求 loop_mode != "conversation",且没有 btw_enabled 守卫。

禁用路径把 loop_mode 设成 conversation,所以这俩分支在 BTW 关闭时永远不进。补测试:btw_enabled=False + computer_use_runtime=local 必须仍调用 _apply_local_env_tools

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:local/sandbox 工具应用恢复 master 语义(仅按 computer_use_runtime 分支,无 loop_mode 门控);对话循环的隔离由 internal.py 在 BTW 开启时把 runtime 覆写为 none 实现,与 master 行为兼容。

Comment thread astrbot/core/astr_main_agent.py Outdated
_get_workspace_path_for_umo(event.unified_msg_origin)
)
if runtime == "local"
if runtime == "local" and loop_mode == "work"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

workspace Skills 同样被 loop_mode=="work" 误伤

btw_enabled 只包了 _filter_skills_for_loop。workspace Skills 仍要求 loop_mode == "work"。BTW 关闭时 loop_modeconversation,local runtime 的 workspace Skills 被清空。

现有 TestEnsurePersonaAndSkills 被改成传入 loop_mode="work",盖住了这条回归。条件应为 runtime == "local" and (not btw_enabled or loop_mode == "work")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:workspace Skills 判据改为 runtime == "local" and (not btw_enabled or loop_mode == "work");TestEnsurePersonaAndSkills 的既有断言保持,另加 disabled-path 测试锁定行为。

Comment thread astrbot/core/auth/service.py Outdated
# actions the work loop elevates; unlisted tool actions and
# non-tool high-risk actions (system/identity/extension
# management) fall through to the dashboard-only deny.
pass

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

产品决定未落地:IM 提权通道仍在

默认关闭 + 空允许列表 fail-closed,解决的是「默认全开」。2026-09-05 的产品决定是:不要合入 IM 自动提权。这段 pass 仍把 btw_work_elevation 当成 Dashboard step-up 的等价物。

运维一旦在矩阵里勾选动作,IM operator/root 就会跳过二次验证(step-up)。若 09-05 决定仍有效,删除此分支,高风险继续 high_risk_dashboard_only。若产品现在接受显式矩阵,需要人类维护者在本 PR 上明确改口;文档改写不能单方面推翻该决定。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

experimentally accepted and could be merged

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

人类决策:experimentally accepted and could be merged。本项(IM 显式 elevated_actions 矩阵 / WebChat 二次验证短路)标为 fixed(accepted)。保留空名单 fail-closed 与角色检查。

AI-Generated: true
Generated-At: 2026-09-06T16:16:46Z

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复(按 09-05 产品决策直接移除而非默认关闭):删除 AuthorizationService 的 btw_work_elevation 分支、btw_elevated_actions 配置键与元数据、internal.py 的提权盖章、Dashboard BtwElevatedActionsSelector 组件与 i18n。IM 高风险 tool.* 无条件保持 Dashboard-only;新增回归测试锁定陈旧提权元数据也无法解除拒绝。文档同步改写为「工作循环不提供任何 IM 提权通道」。

# initialize agent sub stage
self.agent_sub_stage = AgentRequestSubStage()
await self.agent_sub_stage.initialize(ctx)
self.conversation_loop = ConversationLoop()

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260904-pipeline-001 仍在

ProcessStage 永久换成 ConversationLoop。关闭时是透传包装,不是与当前 master 的 AgentRequestSubStage 同构。AGENTS.md:靠包住当前 Process 入口才能存活的功能,是错误设计。

分类应做成当前 Agent 子阶段的前置钩子;btw.enabled=False 时本文件应继续直接持有 AgentRequestSubStage

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:ProcessStage 在 btw.enabled=False 时直接持有并初始化 AgentRequestSubStage(无 ConversationLoop 包装,configure_detached_work 为空操作);开启时才构建 ConversationLoop 并把同一个 Agent 子阶段交给它。文件结构与当前 master 的直持形态一致。

Comment thread tests/unit/test_btw.py Outdated
)
assert (
await classifier.classify(SimpleNamespace(message_str="帮我搜索一下附近餐厅"))
is TaskType.WORK

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

分类器假阳性被单测锁成正确行为

测试名写 word-boundary,断言却把「search for a restaurant」「帮我搜索一下附近餐厅」「what is the research paper about」标成 WORKresearch 本身就在默认关键词里,所以测不到 “search 不在 research 内触发”。

默认关键词仍含「搜索 / 查询 / search / research」。启发式虽默认关,运维一开分类器就会把闲聊送进工作循环。删掉过宽词,或把这些用例改成断言 CONVERSATION

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:从 DEFAULT_WORK_KEYWORDS 移除搜索/查询/search/research;测试更名并改为断言这些输入为 CONVERSATION,同时保留词边界断言(剩余关键词不会在别的词内部命中)。

Comment thread tests/unit/test_astr_main_agent.py Outdated
)
)
)
config = ama.MainAgentBuildConfig(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

空测:未设 btw_enabled=True

MainAgentBuildConfig.btw_enabled 默认 False_filter_plugin_tools_for_loop 会直接 return。断言 names() == ["plugin_tool"] 在过滤器未运行时也成立。补上 btw_enabled=True

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:新增内置 /work 指令(Orbit command_id,GreedyStr 参数)作为工作入口;处理器在事件上打 btw_loop=work 标记后交还 pipeline,不依赖 classifier 开关。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上一条回复贴错了位置(该条对应 /work 指令):已修复——新增内置 /work 指令(Orbit command_id,GreedyStr 参数),处理器打 btw_loop=work 标记后交还 pipeline,不依赖 classifier 开关。

)


def test_runtime_entry_points_use_the_shared_application_runner() -> None:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

无关删除

本提交删掉了 test_runtime_instance_lock_module_does_not_import_coretest_cli_root_helper_does_not_import_core 以及 FileLock 断言。runtime_instance_lock.py / CLI root helper 未被本 PR 改动。请恢复这些门闩。

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

人类决策:Non-blocking。本项标为 fixed(accepted residual)。无关 import-boundary / FileLock 测试删除不再作为合入阻塞。

AI-Generated: true
Generated-At: 2026-09-06T16:16:46Z

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:该测试补上 btw_enabled=True,断言不再空转。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上一条回复贴错了位置(该条对应空测修复):已修复——test_filter_plugin_tools_for_loop_honors_explicit_both_assignment 补上 btw_enabled=True。

Comment thread .pre-commit-config.yaml Outdated
# (tests/unit/test_protocol_function_coverage.py via get_type_hints),
# so the import must stay. --py313-plus upgrades everything up to
# 3.13 syntax without treating PEP 563 as redundant.
args: [--py313-plus]

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

策略改动混进 feat(btw)

AGENTS.md 仍写 pyupgrade --py314-plus。把 hook 降到 --py313-plus 是仓库级策略,不是 BTW 功能。若必须保留 PEP 563 import,单独 chore/build 提交,并同步改 AGENTS.md

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non-blocking

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

人类决策:Non-blocking。本项标为 fixed(accepted residual)。pyupgrade --py313-plus 不再作为合入阻塞。

AI-Generated: true
Generated-At: 2026-09-06T16:16:46Z

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:test_import_boundaries.py 直接取用 upstream master 版本,runtime lock / CLI root helper 测试与 FileLock 断言全部恢复(24 个用例通过)。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上一条回复贴错了位置(该条对应无关删除):已修复——test_import_boundaries.py 直接取用 upstream master 版本,runtime lock / CLI root helper 测试与 FileLock 断言全部恢复。

"""
global _default_manager
_default_manager = manager

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

进程级单例对多配置档会串

每个配置档有自己的 ConversationLoop / WorkSessionManager,但 register_default 是进程全局。后初始化的管道会覆盖前者。/work status 只能看到最后注册的那份会话表。按 config_id 建索引,或从事件选中的管道取 manager。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

已修复:pyupgrade 钉子移出 feat 提交,独立为 chore(ci) 提交并同步更新 AGENTS.md(说明为何使用 --py313-plus)。

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

上一条回复贴错了位置(该条对应 registry 串扰):已修复——runtime_registry 改为按 profile config_id 键控(register/manager_for/latest_status(config_id, origin)),ConversationLoop 注册时携带 ctx.astrbot_config_id,/work status 通过 event.resource.config_id 选中所选配置的 manager。

@BegoniaHe BegoniaHe left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

交叉验证补漏(相对 15:51Z 再审)

人类维护者已把下列公开项降为非阻塞 / 实验接受,台账标 fixed

  • IM 显式提权矩阵(auth/service.py)→ experimentally accepted
  • pyupgrade --py313-plus → Non-blocking
  • 无关 import-boundary 测试删除 → Non-blocking

下面三条是 15:51Z 公开评审正文/行评里没有单独落行的残余,补在 diff 上。不是合入阻塞。

Agent note

  • SHA: 8e9616fcc5f6fd8104f1d295d90b3e5fcf560338
  • 不合并。

AI-Generated: true
Generated-At: 2026-09-06T16:16:46Z

await reply_i18n(self.context, event, "work.status.none")
return
request, status = latest
body = await self.context.i18n.t(event, f"work.status.{status}", task=request)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260906-builtin-stars-001 · 低 · 安全(已确认)

/work status 权限是 session.read(MEMBER)。默认群 UMO 全群共用,这里把 session.request 全文填进 i18n {task} 回给群。任意成员可读他人工作请求原文(约保留 3600 秒)。

15:51Z 再审未落行。建议截断摘要,或把权限提到 session.manage / 按发送者隔离。

非阻塞除非产品要求群内任务保密。

Comment thread astrbot/core/astr_agent_tool_exec.py Outdated
"conversation",
"work",
}:
return toolset

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AUD-20260906-agent-005 · 低 · 安全(很可能)

ConversationLoop 主路径会打 btw_loop。这里在 extra 缺失或非法时 return toolset(不过滤),且 _build_handoff_toolsetcomputer_use 回退是 local。主构建把缺失 extra 当 conversation 并强制 none。cron/后台唤醒事件不复制 extra 时两边语义不一致。

15:51Z 再审未落行。建议缺失 extra 一律按 conversation 失败关闭。

Comment thread astrbot/core/config/default.py Outdated
"hint": "已完成、失败或取消的工作任务保留多少秒以供状态查询。",
"condition": {"btw.enabled": True},
},
"btw.plugin_routes": {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

路由选择器未挂 condition: btw.enabled

15:51Z 再审正文提过、未落行。btw.plugin_routes / mcp_routes / skill_routes 没有 condition: {btw.enabled: True},功能关着仍显示循环分配编辑器。同块其它 BTW 字段已正确挂条件。

非阻塞。补上与其它 BTW 字段相同的 condition。

BTW is an experimental dual-loop Agent mode, disabled by default.  The
conversation loop receives every message; a rule classifier (opt-in)
or the /work command routes tool-intensive requests to a detached work
loop that reuses the established Agent request path.

- Runtime: astrbot/core/agent/btw/ (work loop, sessions, classifier,
  route resolution, per-profile status registry, locale strings) plus
  conversation_loop.py as the BTW-mode ProcessStage entry point.  With
  BTW disabled ProcessStage holds the upstream AgentRequestSubStage
  directly — the Agent path is master-identical.
- Agent integration: MainAgentBuildConfig gains btw_enabled, loop_mode,
  per-loop provider/computer-use overrides, and plugin/MCP/Skill route
  assignments; all loop-specific branches are gated on btw_enabled and
  workspace Skills/local tools keep upstream behavior when BTW is off.
- Authorization: no IM elevation path.  High-risk tool.* actions stay
  Dashboard-only from IM; privilege isolation stays on
  computer_use_runtime.  The conversation loop hard-disables the six
  high-risk tool types while BTW is enabled.
- Work tasks acknowledge, then run in a runtime-owned background task;
  results replay the result-decorate stage onward (reply content-safety
  check, TTS/T2I decoration, platform delivery).  Work entry and status
  queries are real builtin commands (/work <task>, /work status) with
  stable command_ids backed by a per-profile runtime registry; replies
  are locale-aware.
- Dashboard: CapabilityLoopSelector / PluginLoopSelector render the
  per-profile route configuration under the btw.enabled condition.
- Docs: BTW sections in both astrbot-config references; computer.md
  states that IM inherits no high-risk action and the work loop adds no
  elevation path.

Validation: ruff clean; focused BTW/auth/pipeline/builtin-command
suites green (372 tests); dashboard vitest 271/271.
pyupgrade --py314-plus removes `from __future__ import annotations`
(PEP 563 is treated as redundant at min_version 3.14), but the runtime
still evaluates protocol stub annotations eagerly
(tests/unit/test_protocol_function_coverage.py via get_type_hints), so
the import must stay. --py313-plus upgrades all 3.13-and-below syntax
without removing the import. Update AGENTS.md to match.
@YUZHEthefool
YUZHEthefool force-pushed the feat/btw-upstream-sync branch from 191aa16 to 583c628 Compare September 6, 2026 17:57
@YUZHEthefool YUZHEthefool changed the title Sync: merge AstrBotDevs upstream lineage + BTW dual-loop feature into Xero-Team/AstrBot feat(btw): BTW conversation/work dual-loop prototype (disabled by default) Sep 6, 2026
Comment thread tests/unit/test_agent_internal_process.py Fixed
@YUZHEthefool

Copy link
Copy Markdown
Member Author

Re-review round addressed (head now 583c62806, two commits: feat(btw) + chore(ci)):

Blocker 1 — IM elevation removed (2026-09-05 product decision implemented as removal):

  • AuthorizationService btw_work_elevation branch deleted; IM high-risk tool.* is unconditionally high_risk_dashboard_only.
  • btw.elevated_actions config key, metadata entry, dashboard BtwElevatedActionsSelector, and the internal stamp all removed. A regression test proves stale metadata cannot lift the deny.
  • Docs rewritten: the work loop adds no IM elevation path; computer_use_runtime is the only privilege control plane.

Blocker 2 — master-identical when disabled:

  • The disabled builder writes no loop_mode override.
  • _prepare_request_for_agent sandbox/local tool application restored to master semantics (runtime-driven only; conversation isolation comes from internal.py overriding the runtime to none when BTW is on).
  • Workspace Skills: runtime == "local" and (not btw_enabled or loop_mode == "work").
  • New test: btw_enabled=False + computer_use_runtime=local still calls _apply_local_env_tools and still injects workspace Skills.
  • ProcessStage holds AgentRequestSubStage directly when BTW is off (no ConversationLoop wrapper, configure_detached_work is a no-op); ConversationLoop exists only when btw.enabled is on.

Other items:

  • Classifier defaults drop 搜索/查询/search/research; the renamed test asserts those are CONVERSATION and boundaries hold for remaining keywords.
  • /work <task> is a builtin command (Orbit command_id) — the work entry no longer depends on the classifier switch; the handler tags the in-flight event with btw_loop=work and hands it back to the pipeline.
  • runtime_registry keys by profile config_id (register(config_id, manager) / latest_status(config_id, origin)); the command resolves event.resource.config_id, so /work status reads the selected profile's manager.
  • Restored the unrelated deletions: test_import_boundaries runtime-lock/CLI-root cases (24 tests pass) and the CONFIG_METADATA platform-settings docs fields.
  • pyupgrade pin split into its own chore(ci) commit; AGENTS.md updated to --py313-plus with the rationale.
  • Vacuous test fixed (honors_explicit_both_assignment now passes btw_enabled=True).
  • PR title/body rewritten to describe the feature; no merge/sync history in this branch.
  • Dashboard route editors are gated by the backend condition: {btw.enabled: True} metadata (already present for all three route keys), which the dashboard condition engine honors.

Validation: ruff check/format clean; pyright quality gate clean; full unit suite 4604 passed (3 failures = pre-existing Windows-only order-dependent set, passes in isolation); dashboard vitest 271/271; focused BTW/auth/pipeline/builtin suites 372 green.

@YUZHEthefool

Copy link
Copy Markdown
Member Author

@xero-team-bot cc @BegoniaHe

@xero-team-bot

xero-team-bot Bot commented Sep 7, 2026

Copy link
Copy Markdown

cc @BegoniaHe (via @YUZHEthefool)

BegoniaHe and others added 2 commits September 7, 2026 17:18
Replace the /work status subcommand with a GreedyStr /work command so
/work <task> continues into the work loop without the classifier.
Keep /work and /work status as status queries. Drop the classifier
/work prefix, share is_work_loop_enabled, and document the
command-then-agent exception. Command identity is builtin_commands:work.

AI-Generated: true
Generated-At: 2026-09-06T17:32:35Z
Keep BTW conversation-loop computer-use isolation while adopting
master's default computer_use_runtime of none.

AI-Generated: true
Generated-At: 2026-09-07T17:40:52Z
Replace discussion identifiers with the published Issue and PR links,
record the stacked feature delivery, and clarify unfinished experiments.

Refs: #122
AI-Generated: true
Generated-At: 2026-09-10T16:54:52Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract the GreedyStr work entry from PR #28 through the current command
schema and public SDK. Keep empty input and status reserved for the
separate status-query slice; task submission needs both loop switches.

Fixes #124
AI-Generated: true
Generated-At: 2026-09-10T16:01:19Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract status queries from PR #28 through a lazy SDK read helper.
Bind managers to initialized profile pipelines and remove only the closing
pipeline's registration. Keep queries scoped to the profile and origin.

Fixes #127
AI-Generated: true
Generated-At: 2026-09-10T16:09:51Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract the loop-specific model settings from the original PR #28 prototype.
Preserve session selection when a loop override is empty or BTW is disabled.

Fixes #128
AI-Generated: true
Generated-At: 2026-09-10T15:25:34Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract Computer Use boundaries from the original PR #28 prototype and
apply them through the current request tool catalog. Keep conversation
requests and handoffs free of computer tools, and let work select the
inherited, local, sandbox, or disabled runtime without changing authority.

Fixes #129
AI-Generated: true
Generated-At: 2026-09-10T15:38:41Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract the GreedyStr work entry from PR #28 through the current command
schema and public SDK. Keep empty input and status reserved for the
separate status-query slice; task submission needs both loop switches.

Fixes #124
AI-Generated: true
Generated-At: 2026-09-10T16:01:19Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract status queries from PR #28 through a lazy SDK read helper.
Bind managers to initialized profile pipelines and remove only the closing
pipeline's registration. Keep queries scoped to the profile and origin.

Fixes #127
AI-Generated: true
Generated-At: 2026-09-10T16:09:51Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract the loop-specific model settings from the original PR #28 prototype.
Preserve session selection when a loop override is empty or BTW is disabled.

Fixes #128
AI-Generated: true
Generated-At: 2026-09-10T15:25:34Z
BegoniaHe pushed a commit that referenced this pull request Sep 10, 2026
Extract Computer Use boundaries from the original PR #28 prototype and
apply them through the current request tool catalog. Keep conversation
requests and handoffs free of computer tools, and let work select the
inherited, local, sandbox, or disabled runtime without changing authority.

Fixes #129
AI-Generated: true
Generated-At: 2026-09-10T15:38:41Z
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants