feat: 近七天反馈四主题:投递可靠性、会话后端、调度隔离、交互管控 - #1396
Conversation
traex 冷启动 0.6s 帧已画出 composer 与 context 状态条(命中现有 readyPattern)但 banner 仍是 model: loading,首条可能被贴进未就绪 TUI。按真机采样(0.205.1/0.201.x)为 traex 补上与 codex 逐字一致的 startupPending/Ready pattern,复用既有 deferFirstPromptTimeoutUntilReady, worker 侧零改动。 opencode/opencode2 无可靠 prompt 锚,新增适配器可选 firstPromptQuiescenceMs,IdleDetector 仅在本 spawn 首次 idle 前对无 readyPattern 的适配器使用 4s 静止窗口,之后恢复 2s;startup hold、 spinner guard、static-busy latch、completion 500ms 均不变。 Co-Authored-By: Claude Code <noreply@anthropic.com>
新增纯函数 submit-failure-diagnosis 服务,在 submit_unconfirmed 用户卡发出前按 屏幕门(登录/菜单/草稿停泊) > PTY 活跃度弱证据 分级: logged_out/interactive_menu/draft_parked 命中屏幕实证时改发可操作的 submitDiag 卡(zh/en),still_active 在既有 2 次弱证据重查之外最多再 静默 3 次(复用 armDeferredRecheck,有链 fence 与硬上限),unknown 与 ZMX(屏幕非权威)维持原卡。 durable terminal 错误码、dispatchAttempt 守卫、submit-failure-chain 与 submit-confirmation 判定零改动;接线仅 scheduleSubmitFailureNotify 内一处。 Co-Authored-By: Claude Code <noreply@anthropic.com>
Co-Authored-By: Claude Code <noreply@anthropic.com>
T292:清理候选谓词原仅接受 status==='idle',无 worker 的 dormant 行
在计数、按钮与端点三处全部漏算。
- session-cleanup 增加 isDormantCleanupCandidate,复用 idle 全部
安全排除项(locked/pendingRepo/tuiPromptActive/agentAttention),
额外要求 webPort 为空且满足同一空闲时长阈值
- selectCleanupCandidates 返回 {idle,dormant},清理执行两组并集,
dormant 行走既有 close 路径:destroyUnregisteredPersistentBacking
先回收 tmux/herdr/zellij 后端再删记录(adoptedFrom/queued 跳过)
- sessions-page 计数拆为「空闲 N / 休眠 M」,popover 增加语义说明;
端点与请求体不变,WYSIWYG 仍按可见行 id 复核谓词
- i18n 仅追加 cleanupDormant.* 键,zh/en 同步
Co-Authored-By: Claude Code <noreply@anthropic.com
P3,对应反馈 032/132/203a/243 及旧版 tmux 兼容(C1/C3): - ensure-tmux: childFailureReason 在 ENOENT 之前增加 EPERM/clone3/ operation not permitted 分支,明确「tmux 已安装、容器 seccomp 禁止进程克隆」;新增 classifyTmuxProbeFailure(missing/ env-denied/generic,不确定一律 generic)、parseTmuxVersion、 getTmuxVersionCached(成功进程内缓存,失败仅缓存 10s,绝不抛错)、 tmuxVersionAtLeast(null 视为 false 以维持旧行为) - backend-selector: tmux env-denied 卡只给 seccomp 放行与 BACKEND_TYPE=pty 应急说明(含非持久警告),不再出现任何安装命令; missing/generic 文案不变 - tmux-pipe-backend: resize 在 >=2.9 用 resize-window,已知旧版 回退 resize-pane;window-size largest 仅在 null 或 >=3.1 执行; tmux-backend adopt 路径同步 3.1 门控;版本不可解析维持现状 - worker.ts read-isolation unknown 卡补操作指引(勿 kill-server、 后端恢复自动重探),fail-close 语义不动 - 测试:backend-gate +4、tmux-functional-probe 新增 EPERM/分类/ 版本解析用例并保留原 EMFILE 重试断言、tmux-pipe-backend +6 版本矩阵 Co-Authored-By: Claude Code <noreply@anthropic.com
P1,对应反馈 022/030/072/100a/132/214/239/243(C1/C3):worker 就绪前退出与熔断卡此前只有裸 exit code / crashed N times,真正死因 只留在 daemon.log。 - 新增 worker-stderr-ring:per-worker 有界环(200 行/8KB,标记行 20 行/2KB 置顶保留),随 fork 闭包生命周期、无全局表;render 标记行在前、普通尾部在后,最终硬截;复用 crash-log 的 ANSI 清洗 - worker-pool: forkWorker/forkAdoptWorker 各挂一环,stderr 行为 ([t:err] 日志)不变;crash-loop 卡仅在无 logTail 时补环尾 (10 行/1500 字,有 logTail 维持现状不重复);preReadyExit 通知追加 8 行环尾,仍只发一次 notifyStartupFailure - worker.ts: uncaughtException/unhandledRejection 退出前 best-effort sendAndFlush worker_fatal(一次性、截 4096 字、失败不阻塞 exit); isIgnorableStreamError 早退与既有 teardown 顺序保持不变 - types.ts 末尾追加 worker_fatal;i18n 追加 workerDiag.recentStderr - tmux-pipe-backend: pipe-pane 终局失败后 best-effort 执行一次 display-message pane_dead/pane_dead_status 与一次 capture-pane (各 1000ms 超时、tmuxEnv、绝不抛错),确认 pane 内 CLI 即退时 改写为「启动后立即退出 exit status=N + 最后一屏 + 原始首行」; 探测不确定(含 server 级故障)静默退化为原始错误;重试逻辑不变 - 测试:worker-stderr-ring 12 例;crash-loop-diagnostic 新增环回退/ 标记行存活/不与 logTail 重复/pre-ready 通知含环尾; tmux-pipe-backend 新增 pane 死亡证据 5 例 Co-Authored-By: Claude Code <noreply@anthropic.com
Co-Authored-By: Claude Code <noreply@anthropic.com>
# Conflicts: # TEAM-REPORT.md
- scheduled-turn-provenance 的 turn id 正则放宽到 schedule-store
允许的 [0-9a-z_]{1,50},修复 wf3_<46hex>/wf_<47hex> 工作流长
ID 被拒导致首个 workflow 命令秒败(turns=0)
- 绑定判断改为 sessionChatId ∈ effectiveScheduleChatIds(task),
多群任务在次级群不再确定性 binding_mismatch;查任务失败 fail-closed
- botmux-schedule 与 template-bindings 透传 ownerOpenId,只接受精确
$ref: context.initiatorOpenId(presence-gated),拒绝字面量、params
与跨节点注入;缺 initiatorOpenId 时 fail-closed,不回退 bot 身份
- dag 的 botmux-schedule 输入白名单加入 ownerOpenId,端到端链封闭
- ownerOpenId 进 canonical input,undefined 槽位仍被 hash 丢弃,
既有任务的幂等哈希字节不变;不新增 ownerUnionId
- schedule-store 落地任务 ID 字母表/宽度校验,schedules.json 键与
任务输出目录段拒绝路径分隔符等字符
- 同步修正测试中的连字符固定 ID(改为下划线)
Co-Authored-By: Claude Code <noreply@anthropic.com>
executionPosition 增加 opt-in 的 'task':每个定时任务拥有自己的 专属话题,同任务每次触发续入同一会话,不同任务互不相干,默认 执行位置与既有任务行为不变。 - 首次触发:非静默先发种子消息、以 om_ 消息为 root 建话题会话并 回写 task.rootMessageId;静默使用稳定虚拟锚点 schedule-task:<taskId>(不再每次触发换新 schedule-run 锚点), 首次 botmux send 物化后提升到 om_ 键 - 未物化的静默任务遇重启关闭不复活;已物化任务重启后按提升后 root 恢复为话题会话 - 持旧快照的触发穿过物化窗口时,在虚拟键锁内复查 store 权威 root 并重入 om_ 槽位,杜绝第二个隐藏会话覆盖 root 分裂历史 - 仅支持单群任务;NL 关键字(独立话题/专属话题/dedicated topic)、 scheduler、command-handler、dashboard IPC、卡片模型与文案、 定时卡片、Dashboard 表单、zh/en 文案全链路透传 - workflow botmux-schedule 接受 task 位置,拒绝外部自带 root - schedule-store 重载白名单保留 task 位置,避免被归一为 undefined Co-Authored-By: Claude Code <noreply@anthropic.com>
- schedule 中英文档:四种执行位置总览、任务独立话题章节 (同任务续同话题、任务间隔离、首火物化、关键字、卡片循环、 单群限制、每任务模型仅首火生效) - webhook 中英文档:网络前置条件(7891 Dashboard 端点、内网/ 公网反代与 BOTMUX_PUBLIC_URL、Service Mesh Egress、不内置 内网穿透、飞书消息走长连接),注明接入点锚点隔离二期支持 Co-Authored-By: Claude Code <noreply@anthropic.com>
- bots.json 支持 blockedUsers 原始条目,按 bot 自有应用解析到 resolvedBlockedUsers,复用 allowed-users sidecar(retainKeys 取并集) - evaluateTalk 在 allowedUser 正向后、所有其它放行腿之前直接拒绝 (reason='blocked'),open/p2p 等模式同样生效;canOperate 同步前置 - owner/管理员写入守卫:与 resolvedAllowedUsers/owner 冲突拒绝落盘 - 黑名单用户抑制全部授权请求卡(含 ask 点击申请与外部 bot 自愈路径) - daemon 启动解析(含 contact API 降级 warn-only)+ IPC/Dashboard 管理面 - listener include_only 不受影响,黑名单只管 talk/operate - 顺带修 revokeGrant 写 sidecar 时未保留 blockedUsers 键的问题 Co-Authored-By: Claude Code <noreply@anthropic.com>
- 仅接受环境/进程祖先推断出的会话 id,任何显式 id 标志(含 --session-id)一律 usage error(exit 2),换 URL id 仍由沙箱 capability 绑死返回 403 - 沙箱 aperture 正则加入 rename;daemon 落 canonical title (source='agent'),原生 CLI 不支持/离线时仅提示降级,不影响标题 - 回执明确区分 botmux 会话标题、群名(chat rename) 与 omt 话题名 (飞书无话题改名 API,首条消息即话题名) - 新增 botmux-session-rename skill,只讲会话标题、不含群改名 Co-Authored-By: Claude Code <noreply@anthropic.com>
- daemon 新增 GET/PUT /api/blocked-users 与 PUT /api/chat-group-grant 裸 loopback 路由(生产态仍过全局 trusted-host HMAC 闸);grants/chat 支持可选 quota/durationMs,缺省保持旧 CLI 线格式逐字不变 - host dashboard 仅在代理区新增三条 per-bot 转发,四路径均非 manager 不可达(401),不进 public-read 白名单 - bot 默认配置新增黑名单原始条目编辑(懒加载折叠区,不提供 allowedUsers 任何写入口) - 群成员弹窗新增成员授权与封禁:按在群 bot 视角切换(ou_ 不跨 app)、 人/机器人分组、搜索、多选、≤50 批量、额度/有效期、整群授权按钮 - 卡片行为新增静默模式一次性预设:一次 PUT 联动三开关,关闭零写回, 派生条件消失自动熄灭,不做持久绑定 Co-Authored-By: Claude Code <noreply@anthropic.com>
- 新增 permissions 文档(zh/en):四层授权判定链、入群≠授权、 /grant 整群 vs @人额度 vs oncall 适用场景、blockedUsers 语义 - 新增 mention-mode 文档(zh/en):四种提及模式与八种放宽例外 - session-model/cards/cli-commands/slash-commands/oncall/bots-json/ faq/dashboard 同步 session rename、静默预设、黑名单管理面 - 侧边栏纳入新页面,zh/en 成对更新 Co-Authored-By: Claude Code <noreply@anthropic.com>
冲突仅 src/i18n/{zh,en}.ts 文件尾并列追加:保留团队1 的
submitDiag.* 三键与团队3 的 schedulePos.* 五键;web/i18n.ts
由 git 自动合并。整树 bun run build exit 0。
Co-Authored-By: Claude Code <noreply@anthropic.com>
- blockedUsers 黑名单预否决腿:位于 allowedUser 正腿之后、其余所有 放行腿(oncall/peer/team/chatGroup/grant/open/p2p)之前,bot 路径、 canOperate、发卡/ask 点击/外部触发位点/命令触发同拦,owner 不可黑 - botmux session rename + skill,rename 进 daemon 窄认证 aperture, 换 URL sessionId 仍被 sessionCliIpcAuth 拒绝 - Dashboard 成员批量授权(额度/有效期)、整群授权、黑名单管理面与 quietPreset 静默预设;host 非 manager 401、daemon trusted-host fail-closed - sidecar 缓存 allowed∪blocked 并集 retainKeys,两表互不回收 - 文档包 permissions/mention-mode(zh/en) - 唯一冲突 src/dashboard/web/i18n.ts 文件尾并列追加:团队3 schedulePos 五键与团队4 blocked/grantAdmin/quietPreset 59 键 zh/en 对称并列, 键集恰为两父并集(各 2975 键、无重复),128 项值逐字校验零差异 Co-Authored-By: Claude Code <noreply@anthropic.com>
blockedUsers 是纯否决腿,但非 @ 消息在 checkGroupMessageAccess 落 'ignore' 后仍会进入 autoStartOnNewTopic 分支,被当作新话题种子复活 成会话,绕过黑名单。在该分支 shouldAutoStartOnNewTopic 之前补 blocked 短路:被拉黑者在开启自动开工的话题群发的非 @ 消息彻底静默。 relax 中的 messageListener 是 owner 显式内容观察者订阅,属既有语义, 不在此否决。新增端到端回归(黑名单种子不触发 handleNewTopic/ handleThreadReply),并做过反向验证(移除守卫则用例如期失败)。 Co-Authored-By: Claude Code <noreply@anthropic.com>
合并反馈优化四支与工作期间上游推进的三个改动(群新话题默认模型、
话题内附件识别、Dashboard 调度状态同步)。
冲突处理:
- groups-page.tsx:成员授权与群新话题默认模型两个 fieldset 占同一
槽位,拆为并列两个区块。
- schedule-store 任务 ID 字母表校验([0-9a-z_]{1,50},拒绝路径
分隔符等)与上游调度同步测试的连字符 fixture 冲突;生产 id 仅
randomUUID(8) hex 与 wf_/wf3_+sha256,从不含连字符,按字母表
收紧意图把上游 fixture 改为下划线,不放松校验。
合并后整树 build exit 0;四团队 ∪ 上游触达的 53 个测试文件
--no-file-parallelism 全绿(2015 passed + 1 skipped)。
Co-Authored-By: Claude Code <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9662a52f56
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const [executionPosition, setExecutionPosition] = useState<'top-level' | 'topic' | 'new-topic' | 'task'>( | ||
| editing && scheduleExecutionPlacement(editing) === 'thread' | ||
| ? 'topic' | ||
| : editing && scheduleExecutionPlacement(editing) === 'new-topic' ? 'new-topic' : 'top-level', | ||
| : editing && scheduleExecutionPlacement(editing) === 'task' | ||
| ? 'task' |
There was a problem hiding this comment.
Preserve dedicated-task mode when opening the edit form
This task branch is unreachable after the dedicated topic has materialized: composeScheduleRow() projects a rooted task through resolveTaskExecutionPosition() as topic, so scheduleExecutionPlacement(editing) returns thread and the preceding branch initializes the form as topic. Saving an unrelated field then sends executionPosition: 'topic', silently converting the dedicated-task configuration and preventing later edits, such as changing its group, from retaining the create-a-new-dedicated-topic behavior. Preserve the stored task identity in the management DTO/form rather than deriving it solely from current placement.
AGENTS.md reference: AGENTS.md:L129-L129
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已在 2e81988 修复。新增 initialScheduleEditPosition(editing):表单初始位置以存储身份为准——物化后的任务行虽经 scheduleExecutionPlacement 投影为 thread,只要存储 executionPosition === 'task' 仍初始化为 task,保存无关字段不会再把 task 降级成 topic。新增 dashboard-schedules-ui.test.ts 用例覆盖物化 task / rootless task / topic / new-topic / top-level / null 六种初值。
| // Leaving the fresh-topic state parks at top level. The retained root is | ||
| // never reused to cycle back into a topic silently — that was the | ||
| // adopt-topic leak. | ||
| else if (current === 'new-topic') executionPosition = 'task'; |
There was a problem hiding this comment.
Reject multi-chat tasks before toggling into task mode
When a multi-chat task is currently new-topic, the body-less compatibility /api/schedules/:id/delivery route reaches this transition and persists executionPosition: 'task' without the multi-chat validation enforced by addTask() and updateTask(). The next fire then executes the supposedly single-group dedicated task for every target, with each target competing to write the task's single rootMessageId. Check the effective target count before this transition and return multiple_chats_task_unsupported.
AGENTS.md reference: AGENTS.md:L129-L129
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已在 2e81988 修复。new-topic → task 的投递切换分支现在先用 normalizeScheduleChatTargets 计算有效目标数,多于一个群时返回 multiple_chats_task_unsupported、不落盘、不发广播,与 addTask/updateTask 的校验对齐。新增 scheduler-toggle-delivery.test.ts 用例:多群 new-topic 任务切换被拒绝、存储不变。
| anchor = await sendMessage(larkAppId, task.chatId, topicSeed); | ||
| // Write the root straight into the task row (store call, not the | ||
| // scheduler wrapper/event bus): every later fire resolves to this exact | ||
| // thread and resumes the session created below. | ||
| scheduleStore.updateTask(task.id, { rootMessageId: anchor }, larkAppId); |
There was a problem hiding this comment.
Recheck the task root before creating its seed topic
If two executions are admitted from rootless snapshots of the same non-silent task—for example, two near-simultaneous run-now requests—the first execution can persist its root before the second reaches this code, but the second never rereads the task and posts another seed anyway. Each invocation then writes a different root and starts a separate session, splitting the history that this mode promises to keep in one topic. Serialize root creation by task identity or reread/CAS the task before the Lark side effect.
AGENTS.md reference: AGENTS.md:L129-L129
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
已在 2e81988 修复。非静默首火的「重读 root → 发 seed → 写回」整段用 withActiveSessionKeyLock 串到与静默分支相同的稳定虚拟键 schedule-task:<taskId> 上:第二次 rootless 执行入链等待,胜者写回 root 后败者在锁内重读,直接复用同一 root 与同一会话,不再发第二个 seed。锁序 virtual→real,与物化提升 helper 一致,无锁序反转。新增并发用例(sendMessage gate 卡在竞态窗口内断言 seed 仅 1 次、root 写回仅 1 次、两执行共享同一 session/worker、turnId 匹配),并做过反向验证:把锁键改成 turn 唯一键后用例稳定变红。
CI 的 unit 分片在 Node worker + frozen-lockfile 安装的 lark SDK 下运行, registerBot 对「空 appSecret 且非 apiOnly」的测试配置构造真实 Lark.Client, SDK ctor 抛 7104(appSecret or clientAssertionProvider is required), blocked-users-ipc 的 10 个用例失败。 本地共享 node_modules 是较旧 SDK,且 bun/vite 转译下空 secret 仅告警不 抛,导致 bunx vitest 本地全绿、CI 红的环境假阴性。 这些路由本就是 store 结果上的薄适配、不发飞书请求,按 blocked-users-talk 的既有方式 vi.mock 掉 @larksuiteoapi/node-sdk(FakeClient),从根上隔离 SDK 版本与网络。全 test/ 静态排查确认本文件是唯一「空 secret + 非 apiOnly + 真构造 Client」的漏点,其余空 secret 用例均带 apiOnly 或不经过 registerBot。bun 与 node 两种 runtime 各 16/16 通过。 Co-Authored-By: Claude Code <noreply@anthropic.com>
|
你好,这是自动评审的初步意见,最终以维护者审阅为准。 本次评审基于「PR 合并最新 origin/master(d40c0a281)」的本地分支进行,主要发现: 1. 一处建议修复(小改动) 2. 两处文档冲突需要您解 其余非阻断建议(可后续处理):
整体改动质量很好:黑名单两道闸(talk/operate)、定时任务专属话题的懒创建与双重锁晋升、休眠清理的 webPort 守卫都验证通过,构建与测试全绿。修复上述第 1 点并解掉文档冲突后即可进入合入流程。 |
- session-manager: 非静默 task 首火的「重读 root→发种子→写回」改用稳定 虚拟键 schedule-task:<id> 串行化,两次近乎同时的 run-now 只发一条种子、 共用同一会话;落败者读到胜者写回的 root 后续接,锁序与物化提升一致 - scheduler: body-less delivery 切换进 task 位前补多群校验,与 addTask/updateTask 一致拒绝 multiple_chats_task_unsupported - schedules-page: 编辑表单初始化以存储的 executionPosition 为准,物化后的 task 行虽展示为 thread 投影,保存无关字段不再被静默降级为 topic Co-Authored-By: Claude Code <noreply@anthropic.com>
追平上游 d40c0a2(含 deepcoldy#1383 动态单卡问答、deepcoldy#1388 群标签页、deepcoldy#1389 共享工作目录接力原子性、deepcoldy#1392 setup 扫码、deepcoldy#1397 traex 标题转义、 deepcoldy#1390 herdr 托管识别等)。 冲突处理: - groups-page.tsx:删掉群管理弹窗多包的一层 fieldset,成员权限与 「新话题默认模型」恢复为两个平级 fieldset(自动评审阻断项)。 - docs-site/docs/{zh,en}/slash-commands.md:保留双方——本 PR 的 「@ 策略 / Mention Policy」与上游「群标签页 / Chat Tabs」两节并列。 - worker-pool.ts:forkWorker 的 init 回调同时挂回复卡模式标记 (replyCardModeFor,deepcoldy#1383)与统一的 setupWorkerHandlers (含 stderrRing 第五参)。 - bot-defaults-page.tsx:置顶流式卡开关改复用上游 pinToggle, legacy 模式留在卡反馈组、统一问答模式留在按钮组;本 PR 的静默 预设区 QuietPresetSection 保留在组外、两种模式均可用。 验证:bun run build exit 0(tsc + 三个 typecheck + bundle); Node runtime --project unit 全量 23581 passed / 19 skipped, 仅 3 例环境性失败(plugin-mcp-sandbox 两例缺 bubblewrap; release-ancestry-pin 一例缺 js-yaml 顶层解析,pnpm 布局所致、 干净 master 同红),CI bun 布局与 Ubuntu runner 不受影响。 Co-Authored-By: Claude Code <noreply@anthropic.com>
成员权限面板单行解除黑名单时,前端原先按 ou_ 直值从 raw 列表过滤:
条目若是以邮箱 / on_ / 手机形态写入的,PUT 回报成功但实际未删除。
- bot-config-store 新增 removeBlockedUsers(appId, openIds):ou_ 直值
直接出列,其余非 ou_ 条目复用 resolveAllowedUsersWithMap 反查
raw→open_id(contact API 降级时查同一 sidecar 缓存),仅当映射证明
命中目标 open_id 才剔除;证据不足(definitive miss 或 transient 且
无缓存)的条目原样保留,绝不多删。落盘不回退全量 set 路径,避免
列表里历史不可解析条目触发 empty_resolved 挡住本次解除。
- PUT /api/blocked-users 新增 {removeOpenIds} 语义,与全量替换
{entries} 互斥;成员面板解除改走该路由,封禁仍走 GET+全量 PUT。
- 休眠会话清理说明文案改为:adopt 观察的外部会话只断开 botmux 观察
并删除 botmux 侧记录,外部会话本身(连同其中 CLI 进程)不关闭——
与 tmux/tmux-pipe 后端 ownsSession=false 时 destroySession 只
detach 的实际行为对齐(zh/en)。
测试:removeBlockedUsers 6 例(别名反查、无命中幂等、脏条目共存、
末条清除走清道、空目标、未知 app),并做反向验证(关闭反查后 3 例
变红);IPC 新增路由/互斥/非法 2 例;成员面板解除 2 例。Node runtime
bot-config-store 63/63、黑名单链路 52/52、dashboard i18n 439/439。
Co-Authored-By: Claude Code <noreply@anthropic.com>
|
已按评审处理,最新分支合并了当前 origin/master(merge 提交 0c26565,含评审基线 d40c0a2 之后的全部上游改动)。 阻断项
另外两处合并冲突:worker-pool.ts 在 forkWorker 的 init 回调同时保留上游回复卡模式标记(replyCardModeFor)与统一的 setupWorkerHandlers;bot-defaults-page.tsx 让置顶流式卡开关复用上游 pinToggle(legacy 模式在卡反馈组、统一问答模式在按钮组),本 PR 的静默预设区保留、两种模式均可用。 非阻断建议
验证 |
并入 deepcoldy#1362 只读长程任务受限续跑、deepcoldy#1426 worker IPC 就绪门、 deepcoldy#1228 traex Backend Variant 边界、deepcoldy#1431 create-group --chat-mode。 冲突两处,均为路由联合双方各加一个成员,取并集: - src/cli.ts postSessionCliIpc route:本 PR rename + 上游 continuation - dashboard-ipc-server.ts 窄认证路由正则:同上 build 通过;上游侧 17 文件 1024 passed、PR 侧 23 文件 614 passed。 Co-Authored-By: Claude Code <noreply@anthropic.com>
并入 deepcoldy#1425 飞书 WS 长连接代理(Bun)、deepcoldy#1185 TraeX 会话分身、 deepcoldy#1440 超期会话卡停止重试、deepcoldy#1427 codex ZMX 启动输入阻塞、 deepcoldy#1437 dispatch 返回话题线程标识。 冲突三处: - src/utils/idle-detector.ts:本 PR firstPromptQuiescenceMs 字段与上游 startupReadyFromHistory 字段,声明与构造赋值均取并集。 - docs slash-commands(zh/en):上游更新 /fork TraeX 文案,本 PR 更新 /card /cot 并新增 /mention-mode,取上游 fork 行 + 本 PR 三行。 build 通过;上游侧 10 文件 1358 passed、PR 侧 20 文件 622 passed。 Co-Authored-By: Claude Code <noreply@anthropic.com>
deepcoldy
left a comment
There was a problem hiding this comment.
维护者审阅通过。
已在与最新 master 的真合并结果树上验证:与主干零冲突(其中两处路由/字段同形冲突的并集解决已逐点核对,鉴权与调用方均无丢失);bun run build 与 tsc --noEmit 均通过;PR 自身测试、近期合入主干的新增测试及 worker/daemon 源码切片测试合计 3500+ 用例全绿;CI 全绿。
黑名单解封的别名反查、定时任务执行位置等非阻断改进项后续单独跟进。
|
🚀 Released in v3.24.0 |
概述
来自交流群近 7 天反馈,归并为四个优化主题,各自在独立分支开发后整合到本 PR 统一过闸,并已合并最新
master(群新话题默认模型、话题内附件识别、Dashboard 调度状态同步)。四支在函数级不相交,保留各模块 commit,可按 commit / 模块逐节 review。一、投递可靠性
反馈:消息提交后长时间无反馈,不确定 CLI 是否真在跑;个别 CLI 启动卡死无提示。
submit_unconfirmed:worker 在 ready 后长时间仍未确认输入时,发卡前先对失败现场分级(未登录 / 模态菜单 / 草稿未提交等),给出可操作诊断而非笼统超时;复用 deferred recheck + 硬上限 + chain 围栏,不读屏、不改输入语义。二、会话后端
反馈:tmux / clone3 在受限环境报晦涩错误;worker 启动崩溃死因不明;dormant 会话的空闲清理计数混乱。
worker_fatal在 post-ready 不直发用户卡,仅附加到 pre-ready 启动失败卡,避免重复打扰。三、调度隔离
反馈:定时工作流首个命令秒败;多群任务在次级群被误判 binding_mismatch;任务无法独立成话题。
[0-9a-z_]{1,50}(覆盖wf3_/wf_长 ID);绑定判定改为 sessionChatId ∈ effectiveScheduleChatIds,多群 fail-closed;ownerOpenId 只接受精确{$ref: 'context.initiatorOpenId'},拒绝字面量 / params / 跨节点注入。四、交互管控
反馈:无法屏蔽特定打扰者;成员申请 / 授权缺管理面;会话改名只能手动;群内通知时段不可控。
blockedUsers黑名单纯否决腿:位于 allowedUser 正腿之后、所有其它放行腿之前,覆盖发卡、命令、@、自动开工等全部入口;owner 恒不可黑(落盘前求交 + 判定顺序兜底脏数据)。修复被拉黑者的非 @ 消息在「新话题自动开工」分支被当种子复活的旁路(含端到端回归与反向验证)。botmux session rename重命名当前会话;Dashboard 改名走窄认证并绑定 URL sessionId,换 id 返回 403。影响面
worker.ts/worker-pool.ts/event-dispatcher.ts/scheduler.ts/dashboard-ipc-server.ts等。跨 CLI:诊断分级、ready 闸门、idle latch 覆盖多适配器,已在 codex / claude 等回归;跨后端:Pty / Tmux 均覆盖,tmux 门控在条件不满足时回退旧行为;跨会话类型:话题 / 群 / p2p / adopt / restore 均有用例。wf_/wf3_+sha256、从不含连字符,故按收紧意图改 fixture,不放松校验。package.json/bun.lock。测试
bun run build:exit 0。bunx vitest run --no-file-parallelism:53 passed(2015 passed + 1 skipped)(全量并行存在 flaky,故按文件串行跑)。已知边界 / 后续跟进(不阻塞本 PR)
submit_unconfirmed与input_delivery_failed仅在「提交卡后 worker 即刻非抑制性崩溃」的极窄窗口可能叠加,第二卡携带「进程已死」新终态;去重需跨进程感知 worker 内部 submit 状态,风险 / 收益不划算,记为已知边界。🤖 Generated with Claude Code