LoopX Console 产品规格(输入契约)
August 18, 2026 · View on GitHub
版本:v1.2(方向 C:自动克隆 + 同仓库复用) · 适用:loopx-console 全部发布形态(源码导入分发)。
1. 产品定位
LoopX Console 是**「GitHub Issue 持续修复」控制台**,而不是通用目标管理台。
- 唯一开放的用户场景:把 GitHub Issue 交给 BitFun 宿主 Agent 持续修复 (创建 goal → 心跳调度 → turn 执行 → gate 审批 → 直至全部 todo 完成)。
- 其它目标类型(自由目标、非修复类任务)明确关闭:不创建任何 goal, 并给出具体原因。它们将来只能通过绑定具体 loopx capability 开放,且需要 独立的产品评审。
1.1 仓库获取策略(方向 C)
任务绑定的本地仓库目录按以下顺序解析:
- 同仓库复用(默认优先):已记录的项目/克隆目录(
projectByGoal)里 存在该仓库的 checkout 时直接复用(reuseDir),不再重复克隆;确认单 展示「无需重新克隆」。默认落成完全独立的新任务(允许同仓库多任务)。 composer 底部的目标下拉选中已有任务时,输入的内容(链接或自由文本)作为 人类反馈注入该任务,不再走入库。 - 自动克隆(默认):没有可复用的 checkout 时,目标仓库被克隆到稳定的
用户级缓存(
~/.bitfun/loopx-console/repos/<owner>-<repo>),goal 绑定 该克隆;克隆有进度显示(接收对象百分比),已完成仓库走缓存。该目录不在 小应用实例内——删除/重新导入小应用后缓存仍在,同一仓库的后续任务直接 复用(不再重新克隆)。GitHub 校验失败(仓库不存在/网络错误)在确认单 之前就拒绝。 - 本地 checkout(高级选项):设置里选择项目目录后,任务优先绑定该 目录;链接指向其它仓库时不再硬拒绝——控制台自动回退到 1/2 (复用或克隆独立目录)并提示,本地 checkout 绑定保持不变。
- 目标目录按 goal 记录(
projectByGoal),心跳/turn/审批命令各自使用 所属 goal 的目录;看板聚合所有注册表(全局 + 每个项目/克隆目录)。 - 克隆在完整克隆(非浅克隆)——修复类 agent 需要完整历史;缓存命中时 直接复用。未来可加"浅克隆"选项。
2. 输入契约(严格白名单)
支持以下三种 GitHub 链接形态;链接之后可以附加一段修复要求文本 (作为任务前言写入 objective):
| 形态 | 语法 | 行为 |
|---|---|---|
| 单个 Issue | https://github.com/<owner>/<repo>/issues/<n> | 走完整 issue-fix workflow-plan,生成有序 todos |
| 单个 PR | https://github.com/<owner>/<repo>/pull/<n> | 同 Issue(GitHub API 视 PR 为 issue) |
| 仓库首页 | https://github.com/<owner>/<repo>(仅根路径;尾 / 与 query 忽略) | 展开全部 open issues → 确认单勾选 → 批量修复 |
| Issues 列表 | https://github.com/<owner>/<repo>/issues(可带 ?q= 过滤) | 同上 |
拒绝(不创建任何 goal,返回结构化错误码):
| 输入 | 错误码 |
|---|---|
| 自由文本、非 github.com 链接、空输入 | unsupported_input |
github.com 的其它路径(org 首页、/settings、/pulls、/releases、/tree/…、/issues/new、/wiki、commit、search、对比页等) | unsupported_github_path(附带被拒 URL) |
| 一个任务里出现多个不同仓库 | multiple_repositories |
| 目标仓库 ≠ 所选本地 checkout 的 GitHub remote | repository_mismatch(UI 层回退到复用/自动克隆流程,见 §1.1) |
| 所选目录不是该仓库的本地 checkout(无 GitHub remote) | repository_unverified |
| GitHub 上不存在该仓库 | repository_not_found |
| GitHub 校验请求失败(网络/限流) | repository_lookup_failed |
| 仓库/列表展开后没有 open issues | 前端提示(intakeNoIssues),不创建 |
3. 创建流程
- 输入 → 客户端即时分类(输入框 badge:Issue / N 个 Issue / 整仓 Issues)。
- 提交 →
loopx.resolveIntake(只读:分类 + 展开 issues 列表 + 仓库绑定校验; 未选 checkout 时校验 GitHub 仓库存在性并标记autoClone;已记录的 项目目录命中同仓库时返回reuseDir)。 - 确认单(唯一刻意停顿):多 issue 勾选(默认全选、截断标注);复用模式下 展示「无需重新克隆」说明。提交前由 composer 底部目标下拉决定去向: 新建任务(默认,完全独立)或选中已有任务(输入作为人类反馈注入该 任务,不弹确认单、不写 issue todo)。
loopx.taskIntake(事件驱动):clone(自动克隆时,带百分比进度)→ bootstrap → register → plan/todos → refresh → 完成。写入修复 todo 前按 issue URL 去重(同 URL 已有未完成 todo 则跳过)。- 完成后记录 goal 的仓库目录(
projectByGoal),看板与心跳使用它; auto-run 接管。
3.1 停止 / 恢复语义
- 打开即暂停:每次打开控制台(重新导入/重开标签页/重启应用),所有既有 任务一律回到「自动已关」的暂停态,绝不自动续跑;点卡片上的「继续」恢复 自动执行并立即做一次轮询。新创建的任务例外——用户刚发起=明确意图,立即 自动跑。暂停态必须可见:重启后被暂停的任务始终以置灰卡片留在「进行中」 栏(状态章「自动已关」+「继续」按钮),绝不能落入不可见的排队桶而从 看板上消失。
- 停止任务(任务抽屉内)=完整停止:取消进行中的 turn、关闭该目标的
loopx 心跳监控(不再轮询)、关闭自动执行;状态持久化(
stoppedByGoal), 重启小应用后仍保持停止。恢复时还原此前的心跳与自动执行设置,并立即做 一次轮询。 - 取消运行=只停止当前这一次 turn:取消后自动执行关闭(避免立刻重跑), 心跳轮询继续,可手动再次执行。
- loopx 调度策略触发的「已停表」(unchanged ≥ limit →
stop_tick_loop) 是另一套机制:按 loopx 的 reset_token 变化自动恢复,抽屉内的「已暂停 · 点击恢复」只做一次立即轮询。 - 生命周期跟随控制台:控制台关闭/应用退出时,心跳定时器全部停止,进行中 的宿主 Agent turn 全部 cancel;界面显示「没有在运行」即真实没有运行, 不留残留进程。
- 上下文跨重启延续:每个任务的宿主 Agent 会话 ID 持久化到配置
(
agentSessionByGoal)。重启应用/重新导入后点「继续」,复用同一个隐藏 会话——宿主从磁盘恢复该会话,Agent 带着此前的完整对话与工具调用历史 继续,而不是从零开始重新探索。会话已失效(宿主数据被清理)时自动清掉 该 ID 并用新会话重试一次。 - 归档任务永不隐形消失:任务的运行目录被移入 loopx
archived-goals(删除操作或 loopx 自身的归档)后,listGoals仍会把它列出来——以state=archived收进看板底部安静的「已归档」分组(取每个目标最新的一份 归档)。该分组内的卡片只提供「恢复任务」:把运行目录移回goals/并 按最新的registry.global.json.del-bak-*备份重建注册表条目(找不到备份 时用最小条目),恢复后任务回到「自动已关」暂停态,点「继续」接着跑。 已归档任务不轮询、不自动执行。
3.2 中途插话(人类干预)
-
选中已有任务时:输入框内容(自由文字或链接)一律作为人类反馈写入 该任务的 user-lane todo(
--role user --task-class user_action --bound-agent <agent>,不是 user_gate——这是给 Agent 的指令,不是阻塞 决策),loopx 将其作为该 agent lane 的 post-response continuation 投递, Agent 下一步就会读到并据此调整行为。 -
未选中任务时:自由文字自动发给当前运行中的任务(多任务运行中时提示 先点选)。
-
目标选择:优先当前在详情面板选中的任务;否则若只有一个任务在运行则 直接发送;多个任务运行中时提示先点选目标任务。
-
发送后立即做一次轮询(force),自动执行会在下一步消费这条指令; 活动流里记录「你:…」原文。
3.3 发布(提交 PR,默认行为)
publish 类门禁(external_pr_creation / external_review_request 等)是
控制台自己提交 PR 的入口,批准即发布:
- 用户在顶栏「GitHub 设置」配置 fine-grained PAT(Repository 读写),
保存时经
GET /user验证;仅存于本机应用存储。 - 批准发布门禁时(默认动作=提交 PR):
loopx.publishPr执行 检查/创建 fork(POST /repos/{o}/{r}/forks,轮询至就绪)→git push分支到用户 fork(一次性 x-access-token URL,不落 git config)→ REST 创建 PR(head=用户 fork 分支,base=上游默认分支;同分支已有 open PR 时复用不重复建)。 - PR 标题带
[bitfun-loopx]前缀、正文带Created by BitFun LoopX Console (bitfun-loopx).标识——GitHub 上可用"bitfun-loopx" in:title统计本工具产出的全部 PR。 - 创建成功后完成发布 todo 并把 PR 链接写入 todo note,loopx 据此对账, Agent 不再自行 push/建 PR;失败则门禁保持打开、日志写明原因。
3.3.1 全平台可统计标志(commit 层)
- 控制台管理的克隆仓库安装
commit-msg钩子(ensureCommitTrailerHook, 只作用于~/.bitfun/loopx-console/repos/下的缓存克隆,绝不写入用户自选 仓库):每次git commit自动在提交信息末尾补上Co-authored-by: bitfun-loopx <bitfun-loopx@users.noreply.github.com>。 - 每轮 turnPrompt 重装一次钩子(幂等),且任务前言明确要求 Agent 保留该行。
市场版无法写
~下的钩子文件,降级为提示词强制。 - 统计口径(已用 GitHub 搜索 API 实测确认语法有效):
- 提出/打开/合并的 PR 数:
"bitfun-loopx" in:title is:pr [is:merged] - 提交次数:commit 搜索
"Co-authored-by: bitfun-loopx"(仅覆盖进入 各仓库默认分支的提交;squash 合并时 PR 标题前缀会进入默认分支,仍可 用"[bitfun-loopx]"的 commit 搜索兜底) - 代码行数:搜索 API 不提供行数,需按 PR 列表逐个取
additions/deletions(脚本可从标题搜索枚举 PR 后聚合)。
- 提出/打开/合并的 PR 数:
4. 双层强制
- 客户端(ui.js):
taskInputKind/firstUnsupportedGithubUrl即时反馈, 不满足契约时提交被本地拦截,附带具体错误与示例。 - Worker(worker.js):
githubReferences严格分类 +resolveIntake/taskIntake双重守卫。独立调用者(绕过 UI)同样被拦。
两处实现共享同一份语法定义(本文件 §2),修改契约时必须同步两处与本文档。
5. 明确不做(Closed)
- 自由形式目标(等待绑定具体 loopx capability 后单独评审)
- 非 GitHub 仓库(GitLab/Gitee 等)
- org/用户主页、搜索、release、commit、diff、wiki 等页面链接
- 在应用内新建/编辑 issue(用户去 GitHub 建,回来贴链接)
6. 未来候选(不承诺)
- 浅克隆选项(大仓库加速)
- 按 capability 绑定的其它目标类型(需 loopx 侧能力 + 独立评审)
- 市场版(无 worker +
shell.execargv 重构,执行能力收窄) - 运行时随包分发(loopx CLI 二进制捆绑)