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)

任务绑定的本地仓库目录按以下顺序解析:

  1. 同仓库复用(默认优先):已记录的项目/克隆目录(projectByGoal)里 存在该仓库的 checkout 时直接复用(reuseDir),不再重复克隆;确认单 展示「无需重新克隆」。默认落成完全独立的新任务(允许同仓库多任务)。 composer 底部的目标下拉选中已有任务时,输入的内容(链接或自由文本)作为 人类反馈注入该任务,不再走入库。
  2. 自动克隆(默认):没有可复用的 checkout 时,目标仓库被克隆到稳定的 用户级缓存~/.bitfun/loopx-console/repos/<owner>-<repo>),goal 绑定 该克隆;克隆有进度显示(接收对象百分比),已完成仓库走缓存。该目录不在 小应用实例内——删除/重新导入小应用后缓存仍在,同一仓库的后续任务直接 复用(不再重新克隆)。GitHub 校验失败(仓库不存在/网络错误)在确认单 之前就拒绝。
  3. 本地 checkout(高级选项):设置里选择项目目录后,任务优先绑定该 目录;链接指向其它仓库时不再硬拒绝——控制台自动回退到 1/2 (复用或克隆独立目录)并提示,本地 checkout 绑定保持不变。
  • 目标目录按 goal 记录(projectByGoal),心跳/turn/审批命令各自使用 所属 goal 的目录;看板聚合所有注册表(全局 + 每个项目/克隆目录)。
  • 克隆在完整克隆(非浅克隆)——修复类 agent 需要完整历史;缓存命中时 直接复用。未来可加"浅克隆"选项。

2. 输入契约(严格白名单)

支持以下三种 GitHub 链接形态;链接之后可以附加一段修复要求文本 (作为任务前言写入 objective):

形态语法行为
单个 Issuehttps://github.com/<owner>/<repo>/issues/<n>走完整 issue-fix workflow-plan,生成有序 todos
单个 PRhttps://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 remoterepository_mismatch(UI 层回退到复用/自动克隆流程,见 §1.1)
所选目录不是该仓库的本地 checkout(无 GitHub remote)repository_unverified
GitHub 上不存在该仓库repository_not_found
GitHub 校验请求失败(网络/限流)repository_lookup_failed
仓库/列表展开后没有 open issues前端提示(intakeNoIssues),不创建

3. 创建流程

  1. 输入 → 客户端即时分类(输入框 badge:Issue / N 个 Issue / 整仓 Issues)。
  2. 提交 → loopx.resolveIntake(只读:分类 + 展开 issues 列表 + 仓库绑定校验; 未选 checkout 时校验 GitHub 仓库存在性并标记 autoClone;已记录的 项目目录命中同仓库时返回 reuseDir)。
  3. 确认单(唯一刻意停顿):多 issue 勾选(默认全选、截断标注);复用模式下 展示「无需重新克隆」说明。提交前由 composer 底部目标下拉决定去向: 新建任务(默认,完全独立)或选中已有任务(输入作为人类反馈注入该 任务,不弹确认单、不写 issue todo)。
  4. loopx.taskIntake(事件驱动):clone(自动克隆时,带百分比进度)→ bootstrap → register → plan/todos → refresh → 完成。写入修复 todo 前按 issue URL 去重(同 URL 已有未完成 todo 则跳过)。
  5. 完成后记录 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 的入口,批准即发布:

  1. 用户在顶栏「GitHub 设置」配置 fine-grained PAT(Repository 读写), 保存时经 GET /user 验证;仅存于本机应用存储。
  2. 批准发布门禁时(默认动作=提交 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 时复用不重复建)。
  3. PR 标题带 [bitfun-loopx] 前缀、正文带 Created by BitFun LoopX Console (bitfun-loopx). 标识——GitHub 上可用 "bitfun-loopx" in:title 统计本工具产出的全部 PR。
  4. 创建成功后完成发布 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 后聚合)。

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.exec argv 重构,执行能力收窄)
  • 运行时随包分发(loopx CLI 二进制捆绑)