mcpField
S
statuskit

statuskit

github.com/mimukit开发2276 次安装2 天前更新
代码仓库

关于 statuskit

statuskit 是只读的项目状态与下一步建议技能,汇总工作树、GitHub issue、PR、计划和待审文档,并生成单屏仪表板。它按优先完成进行中工作的原则排序,只推荐一个下一步,不执行提交、合并或代码修改。

主要功能

  1. 01汇总仓库、issue、PR 与计划状态
  2. 02生成单屏状态仪表板
  3. 03按完成优先原则排列行动
  4. 04选出唯一的下一步建议
  5. 05以只读方式运行,不修改代码

适用场景

  1. 01暂停一段时间后快速了解项目状况
  2. 02决定先完成哪个进行中的工作
  3. 03查看未整理计划或待审文档
  4. 04根据 issue 与 PR 状态确定后续行动

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/mimukit/skills --skill statuskit

安装后在 Claude Code 中输入/statuskit确认已加载。

附带文件declaration.md

详细介绍

statuskit

当你重新坐回项目旁,想知道 “这个项目现在是什么情况,我最应该先做什么?” 时,statuskit 就是你的入口。它会以 只读 方式检查整个项目,涵盖 Git 工作树、GitHub issue、未关闭的 PR、尚未归档的计划,以及标记为待审核的文档;随后打印一屏 状态仪表板,再完成它最有主见的部分:按照 优先完成 规则为可能的下一步行动排序,并且只选出 一个 最值得采取的行动,将你引导至能完成它的工具包(或普通命令)。

它是一个 读取并提供建议 的工具。它绝不会提交、推送、关闭 issue、编辑 PR、合并、重新标记或编写代码,因为所有变更都发生在它交给你的工具包中,并受该工具包自身的保护。它所做的一切都不会触及远程服务、分支或跟踪器,这正是它的设计目的:你可以随时、随意多次安全地运行 statuskit,重新了解项目情况。它只会写入其写入规则中列出的本地文件。

何时使用

你想在采取行动前了解情况时:比如“我接下来该做什么”“检查项目状态”“这个项目进展如何”“下一步是什么”“项目状态”“帮我了解情况”“/statuskit”,或者离开一段时间后只问一句“这个项目现在是什么情况”。

有一条重要界限:

  • 它不是跟踪器的权威来源。 这属于 issuekit 的职责。statuskit 会读取 issue 的数量和状态,为建议提供依据,并计算一个简单的过时信号。详细的跟踪器健康状况应交给 issuekit:issuekit 回答“我的跟踪器是否准确?”,statuskit 回答“这个项目现在是什么情况,我接下来该做什么?”

排序原则:优先完成

statuskit 选出的行动都遵循同一条规则:“停止开始,开始完成”(尽量减少进行中的工作)。它选出的行动始终是在启动新任务之前,以最少的精力收尾最多进行中的工作。

同一层级内的平局,先按声明的优先级打破,再根据该层级要求执行的操作,在两种信号中选择一种:

  • 继续或完成层级。 选择最近活跃的候选项(issue/PR 的 updatedAt,或分支的最后提交时间)。近期活动可以作为上下文切换成本的替代指标;当你需要切换回一个尚未完成的项目时,最需要减少的正是切换成本。唯一例外是已完成但尚未审核的 PR:没有未完成的工作可供切回,因此应像启动层级一样,按影响力打破平局。
  • 启动新任务层级。 选择解除阻塞的影响力最高的候选项(见下文),若仍相同则选最近活跃的候选项。启动新任务时,没有需要保留的上下文,因此近期活动所衡量的成本为零;相反,值得最大化的是吞吐量:这项工作完成后,仓库能并行推进多少工作。

其他候选项列为备选。优先级和影响力都不会让候选项跨越层级,因为优先完成是核心原则,而两者只用于在层级内排序。只有一个例外:critical issue。 见下文。

优先级

优先级是人对“什么最重要”的明确判断,取自 issuekit 标签集:critical、high、medium、low。 statuskit 排序所依据的其他所有信息都来自对仓库机制的推断;只有这一信号是由人明确给出的,因此它在所有平局判断中都优先,而不是与已有信号并列竞争。

优先级刻度
标签含义排序方式
critical放下手头的一切;优先于正在进行的工作跨层级提升
high优先于其他可处理的问题在同一层级内排序
medium常规优先级;评估后的默认值在同一层级内排序
low值得之后处理;绝不抢占任何事项在同一层级内排序
(none)尚未评估;无人为其排定优先级排在 low 之后

优先级是两个独立标签命名空间之一,statuskit 会同时读取两者。 生命周期(ready、blocked、in-progress 等)说明一个问题是否 可以 处理;优先级说明接下来 应该 处理哪个问题。绝不要从一个推导另一个:一个处于 blocked 状态的 critical 问题仍然是受阻的,若将它推到首位,就会让用户面对一个无法着手的问题。

未评估项排在 low 之后,这并不是对工作的评判。 这是对 问题跟踪器 的判断:无人排定优先级的问题并无优先权,而 statuskit 的全部工作就是选出一个有理有据的下一步。把未标记的问题排在已标记的问题之前,就意味着擅自替用户编造优先权。当未评估项积压很多时,这本身就是发现,应将其呈现出来并指向 issuekit triage,而不是悄悄替用户整理一堆无人排序的待办事项。

critical 是唯一能凌驾于先完成手头工作的优先级

这里的其他所有信号都只在同一层级内排序,这种克制是刻意为之,因为它能避免某个巧妙的数字劝用户放下已经开始的工作。critical 是例外,支持它的理由可以用一句话说清:先完成手头工作,是在无人说明什么重要时采用的启发式原则;而 critical 就是有人明确说明了什么重要。

尽量减少进行中的工作是正确的默认做法,恰恰是因为它不需要任何信息:适用于任何代码库、任何一天,无需询问任何人。critical 标签提供的信息严格优于这一默认做法,也是整个调查中唯一由人刻意设置的信号。若拒绝响应它,statuskit 就会把一个尚未完成的重构排在用户自己标记为紧急的事项之前;这是唯一会让仪表板变得不可信,而不只是出错的结果。

有三条防线可避免这个例外吞没规则:

  • 只有 可处理 的 critical 才会提升。 它必须处于未受阻且开放的状态,因为处于 blocked 状态的 critical 无事可做,所以它会留在应有的受阻表格中;如果它的阻塞项本身可处理,那么被推到首位的就是那个阻塞项。
  • 只有 critical 会提升,其他都不会。 high 不是轻度版的 critical。它和影响力一样,只在同一层级内排序;想要抢占优先级的代码库必须明确标记为 critical,这种门槛正是让这个级别保持意义的关键。
  • 说明被搁置的事项。 当 critical 抢占了原本会胜出的层级时,要同时点明被挤下去的下一步:“#12 是 critical,所以优先处理;你的红色 PR #34 降为第二顺位”。用户看不见的抢占与排序错误无从区分,而这种情况很少见,更应该明确呈现为一个事件。

多个 critical 都可处理时,这本身就是发现。 两个只需通过影响力、再通过新近程度来打破平局;但如果问题跟踪器中有好几个问题都能抢占所有事项,说明这个级别已经失去意义:没有任何事项会为它们而搁置,critical 也就悄然成了新的常态。应在被推到首位的事项上说明这一点,并指向 issuekit triage,它会标记陈旧的 critical 标签,以便识别这种偏移。

解除阻塞的影响力

unblocks(X) 是指 X 落地后会立即变为 完全可处理 的开放问题数量。 它回答的是“这些事项中,哪一项能让最多独立工作马上得以开展?”,并在文件中以可排序列的形式呈现在已有的两张明细表上。 完全 一词承载着这条规则。如果 #19 同时被 #12 和 #23 阻塞,只关闭 #12 并不会让 #19 变得可处理;它只是让 #19 少受一个阻塞,而这对想找事做的人毫无价值。只有移除 #12 后,其未关闭的阻塞项集合为空,该问题才计入 unblocks(#12)。任何宽松一些的定义都会抬高这个数字,并把你引向错误的问题,这比完全不排序更糟。

PR 的杠杆作用取决于它关闭了哪些问题:unblocks(PR #34) 就是其 closingIssuesReferences 中问题的杠杆作用。这会让 Closes 列从一项事实变成优先级,因为能释放三个问题的评审,优先级高于一个也释放不了的评审,不管它们的 CI 状态如何。

在每一层堆叠 PR 中,closingIssuesReferences 都为空,这是平台规则,并非缺少关联。 GitHub 只会在目标分支为仓库默认分支的 PR 上解析关闭关键词,因此,即使某个层级 PR 包含正确的 Closes #123,在其下方的层级合并、GitHub 将它的目标分支改为主分支之前,也不会报告任何关闭的问题。三个读取都共用这个字段,因此在某一层级上会同时出错:该 PR 什么都没关闭,所以不会显示优先级,没有杠杆作用,其分支也不会映射到任何问题。因此,对于 baseRefName 不是默认分支的 PR,应改为从正文中提取 Closes #N,并将提取结果完全按 closingIssuesReferences 的处理方式处理。在本文件的其他地方,提取仍然只是较弱的读取方式:仅对某个层级使用,而且仅当该字段返回为空时使用。

四条规则可确保数字准确:

  • 仅计算深度 1。 不计算级联关系。传递性数字假设中间问题会完成,而不仅仅是解除阻塞;statuskit 不该擅自预测排期。深度 1 天然不会受循环影响,而传递遍历则需要防范 A blocked by B blocked by A。
  • 只计算仍未关闭的阻塞项,与被阻塞集合遵循相同规则。
  • 阻塞项可以是 PR。 在 GitHub 上,问题编号和 PR 编号共用一个命名空间,因此 blockedBy: #34 可能表示“等待合并”,并通过未关闭 PR 的读取来解析。
  • 没有声明依赖关系,就不显示列。 如果仓库的依赖图完全没有边,那么所有值都是 0,这一列反而会说谎:它显示“没有任何东西能解除阻塞”,而真实情况是“没人记录依赖关系”。移除该列,只说明一次(未声明依赖关系;无法计算杠杆作用),并指向 issuekit,因为声明依赖关系属于跟踪器维护工作,而非调研工具的职责。

有两种状态会显示出来,但绝不会被选为头号事项,因为它们需要人为把关,而不是 statuskit 应该推动的优先完成项:

  • 已批准且 CI 通过的 PR(“可合并”),因为是否合并由你决定;
  • 确实在等待别人评审的 PR,这不由你掌控。

两者都会作为事实显示在仪表板中;但都不会成为首要行动。

“不由你掌控”指的是确实存在某个人。 只有在确实有人被请求后,第二种状态才成立:已请求的评审者,或已经评审过的非作者。根据作者身份推断(“你发起了它,所以你一定在等别人”)会让整个仪表板在个人仓库中失效:每个 PR 都是你的,从未有人被请求,而每一行都会永远显示为等待他们处理,与此同时,阶梯却会选出别的事项。因此,应根据 reviewRequests 和 latestReviews 判断是否在等待,绝不能根据 author;如果答案是没人,那么这个 PR 根本不是不由你掌控,而是卡在你这里,应按完整阶梯排序。 statuskit 只为评审加冕,绝不为合并加冕。 这正是让新阶梯不与上面的规则相矛盾的关键:评审一个尚未评审的 PR 是真正的工作,有明确可见的完成标志;而按下合并按钮则是 statuskit 不会越俎代庖的判断。加冕的操作以 已评审 为终点,并将合并决定交还给你。

确定跟踪器

并非每个项目都通过 GitHub Issues 管理工作,而且 gh 能正常运行并不能证明这个项目使用 GitHub Issues。 某个仓库可能已通过 gh 完成身份验证、启用了 Issues,也有四十个未关闭的 Bug 报告,但所有计划中的改动都在 Linear 中。另一个仓库可能一个 Issue 都没有,因为它是昨天才创建的。这两种情况需要截然相反的建议,因此 statuskit 会明确判断,而不是根据 API 是否有响应来推断。

按顺序采用第一个能给出答案的阶梯:

  1. 提示词。 用户已经说明(“我们不用 GitHub issues”“把这个记到跟踪器里”)。明确说明始终优先。
  2. 仓库的 Agent 指南文件(CLAUDE.md 或等效文件)说明在哪里跟踪工作。像 本项目使用 Linear 而非 GitHub Issues 跟踪工作 这样的句子,无论指向哪一方,都足以定论。
  3. 检测:使用计划调查已经执行的 gh issue list --state all 调用,因此无需额外成本。非空数组表示存在。如果错误信息说明该仓库已禁用 Issues,则表示不存在。
  4. 未知。 空数组或其他任何错误(网络、身份验证、速率限制)。空数组无法区分创建仅一天的仓库和使用 Jira 的团队,而调用失败根本无法说明策略。

判断结果有四种状态,本文件中所有依赖跟踪器的规则都以此为准:

判断结果来源Issue 阶梯(†)和 Issues 面板未登记计划检查
存在提示词、指南或非空数组执行执行
不存在提示词、指南或 Issues 已禁用跳过跳过
未知空数组或其他任何查询错误跳过,并说明一次跳过
不可用缺少 gh 或未通过身份验证,或没有 GitHub 远程仓库改为执行纯 Git 阶梯跳过

下文中的没有跟踪器指不存在或未知。查询错误绝不等于不存在。 在 Issues 行中说明一次失败的调用,并按没有跟踪器处理;只有重试才能确定情况,不能直接下结论。即使提示词或指南表明存在跟踪器,但 Issue 查询失败,也同样如此:策略已知,但数据未知,因此跳过 Issue 阶梯,并说明失败的调用。

未知时按没有跟踪器处理,并明确说明。 它绝不声称某个计划尚未登记,绝不加冕“去登记 Issue”,而是在同一行列出两种路径。空数组导致的未知是唯一存在歧义的策略状态。保持未知,不要去探测生命周期标签:模板可能预置了无人使用的标签,而探测只会改变措辞,不会改变操作。如果触发此情况,且用户在场可供询问 → 阅读 declaration.md,然后按其中说明执行。

只有 statuskit 会判定此事。 它必须负责判定,因为它只会为一个操作加冕。其他技能要么传递这一行结论(issuekit、afkkit),要么列出两个去向但不作判定(plankit、grillkit、implementkit)。将推导过程集中在一处,才能避免四个技能逐渐给出四种略有不同的答案。

流程

1. 预检,按来源降级,绝不整体失败

statuskit 以 git 为先:始终由 git 信号驱动,有 GitHub 信号时则用其补充。检测现有条件并灵活适配,而不是直接退出:

  • 不是 git 仓库 → 说明这一点;跳过所有派生自 git 的内容。如果仓库尚不存在,下一步是“从 plankit 开始”。
  • 缺少 gh / 未通过身份验证 / 没有远程仓库 → 降级到下方的纯 git 阶梯。这是一种正式模式,不是错误,因此只需说明一次具体缺项(未安装 gh、运行 gh auth login,或添加 GitHub 远程仓库),然后继续。
  • gh 可用,但项目不通过 GitHub Issues 跟踪工作 → 按确定跟踪器中的说明明确处理。这是策略事实,而非能力事实,因此不会因调用失败而意外出现;Issues 阶梯和 Issues 面板都会据此启用。
  • 没有计划文档 → 完全跳过计划文档的读取。即使存在计划,Plans 面板也是有条件显示的;参见计划调查。
  • 完全没有 shell(例如基于浏览器的 Agent)→ 无法运行调查;打印下方的命令供用户运行,并根据用户粘贴回来的结果进行判断。
2. 调查,只读收集信号

始终收集 git 信号;仅在 gh 可用时收集 GitHub 信号。所有命令均为只读。

git(始终):

  • 工作树:git status --porcelain、当前分支、上游领先/落后情况、git log @{u}.. --oneline(未推送的提交;如果分支未设置上游,则跳过,这本身就是“推送/发布”信号)、git stash list --format='%h %gd %s'(SHA 是 stash 的稳定标识),以及任何包含未合并提交的本地分支。
  • 基准分支,通过 gitkit 获取,而不是假定为 main。下文所有关于“是否为功能分支”和“是否已合并”的判断都取决于它。对于默认分支为 develop 或 trunk 的仓库,假定为 main 会导致整个仪表板判断错误。
  • 分支 → Issue 映射。 通过当前分支的开放 PR 中的 closingIssuesReferences,将当前分支关联到一个受跟踪的 Issue(这是可靠信号,且已在下文读取 PR 时获取);如果没有,再使用分支名称启发式规则。堆栈中的某一层该字段为空,因此在退回到分支名称前,请应用层级回退规则,并读取 PR 正文中的 Closes #N。分支名称模式由 gitkit 提供,因为它负责命名分支(issue-<n>-<slug>);因此应在 gitkit 中读取,而不是在此处再维护一份解析器,否则上游重命名后,这里的匹配就会悄无声息地失效。更宽松的回退方式是使用单独的 #N,或与 Issue 标题匹配的 slug。如果仍无法映射,将非基准分支上的脏分支视为继续,而不是提交。
  • worktree。 调查需要知道某个分支的代码位于何处时,应询问 gitkit,而不是读取路径。statuskit 从不创建或移除 worktree;它只负责报告。
  • CONTEXT.md 信号:进行一次轻量检查,类似于跟踪器过期信号;只报告是或否,不逐项列出,因为具体发现由 domainkit 的 audit 负责。符合以下任一条件时触发。**缺失:**仓库根目录中没有 CONTEXT.md(或 CONTEXT-MAP.md),但存在 docs/adr/ 或 docs/plans/,说明项目有值得命名的领域,却没有术语表。落后:docs/adr/ 中最新的 ADR 文件是在最后一次修改 CONTEXT.md 的提交之后添加的,或者此后已产生至少 50 个提交(先运行 git log -1 --format=%H -- CONTEXT.md,然后运行 git rev-list --count <sha>..HEAD)。如果 CONTEXT.md 只是缺少 ## Overview,则不会触发。 GitHub(仅当 gh 可用时):
  • issue:gh issue list --state open --json number,title,labels,updatedAt,blockedBy,blocking,按生命周期标签分桶(in-progress / ready / stacked / needs-planning / blocked / in-review),并为没有采用这套标签体系的仓库设置一个未标记/其他状态分桶。只显示计数和可采取行动的集合,不做漂移检测。将最近的未标记 issue 视为待分类或规划的候选项,而不是视而不见的工作。
  • priority,从同一个 labels 数组读取,因此无需额外调用:调查已经获取了每个未关闭 issue 的所有标签,而 priority 正是其中四个名称之一。若某个 issue 带有多个 priority 标签,取最高级别(这是跟踪器标签失误,不是状态,issuekit triage 会修复);若一个都没有,则记为 none。如果没有任何未关闭 issue 带有 priority 标签,就移除该列,不要打印一整列空白,并只说明一次(尚未设置 priority;按杠杆效应和更新时间排序),同时指向 issuekit triage。这与全为零的杠杆效应列遵循同一规则,原因也相同:一列值始终不变,看起来像是已核查且结果为空,但实际情况是还没有人填写。
  • 依赖图。 同一次调用返回的 blockedBy 和 blocking 是 GitHub 的原生 issue 依赖,因此图已经解析完毕:无需扫描正文,无需逐个获取 issue,也无需第二次往返。要防御性地读取((.blockedBy // []) | length),不要假定字段布局;如果仓库未使用此功能,则回退到文本约定,即在正文中查找 Blocked by #N / Depends on #N / Blocks #N 行,并在 shell 中用 --jq 提取,确保正文不会进入上下文。两个方向描述的是同一条边;应统一为一种表示。
  • 未阻塞集合:所有既未被阻塞也不处于 in-review 状态的未关闭 issue,保留为编号 + 分桶 + priority + updatedAt + unblocks 计数 + 标题,而不是折叠成一个计数。这是可立即着手处理的列表,仪表板会将其打印为表格,让你无需第二次 gh 调用就能对其中某项采取行动。当 issue 存在仍未关闭的 blockedBy 条目,或带有 blocked 标签时,即视为被阻塞。带有 in-review 标签时即为 in-review,因为其代码已经写好,接下来该进行审查;下方的待审查表会完整列出它,因此在这里重复只会让可立即着手的列表徒增一项无法着手处理的工作。如果仍未关闭的 blockedBy 对应的阻塞 issue 有一个未关闭 PR,则不算被阻塞。 前置工作已完成并推送,因此依赖它的工作现在就能在基于阻塞项的分支上开展;应将其放入此表并标记为 stacked,而不是放进阻塞集合。仪表板本就会读取未关闭 PR,因此这一检查无需额外开销。只有一个方向上出错代价很高:把可堆叠的工作归入“被阻塞”,会将它藏在读者被告知可以跳过的表里,这与本次调查的目的恰恰相反。其他工作都未被阻塞:ready、未标记或需要规划的工作,以及可以继续处理的 in-progress 工作。按 priority 降序、unblocks 降序、最近更新时间排序,因为明确声明的 priority 高于推断结果,杠杆效应用于区分无人排序的事项,而更新时间应作为独立列保留,而不是用作排序依据。
  • 被阻塞集合,同一次读取的另一半,保留为编号 + priority + 等待的事项 + 标题。这里只包含真正需要等待的事项,也就是前置工作尚未完成的情况;阻塞项有未关闭 PR 的事项已移至上方的未阻塞表。即使此表中的事项无法立即着手,priority 仍有价值,因为它能告诉你是否值得追进度的是其阻塞项:一个排在尚未开始的前置事项之后的 critical,是整个仪表板中最有力的理由,足以推动你开始该前置事项;没有这一列,它看起来就和其他等待中的条目没什么两样。若有 blockedBy,阻塞项取自该字段;否则取自 Blocked by #N / Depends on #N 行;若只有单独的 blocked 标签,则不标明阻塞项。保留这三种形式;未标明的阻塞项仍是值得打印的事实。报告 issue 声称 正在等待什么,是在读取事实;一旦开始判断阻塞项是否仍然有效,就进入了 issuekit 的职责范围,应当指向它。
  • 未关闭 PR:gh pr list --json number,title,author,baseRefName,statusCheckRollup,reviewDecision,reviewRequests,latestReviews,isDraft,updatedAt,closingIssuesReferences,分类为你的红色/要求修改的 PR(可采取行动)、无人审查的 PR(可采取行动)、已批准且 CI 通过(仅展示),以及确实在等待他人处理(仅展示)。大型仓库应限制列表长度以保持速度;如果某个 JSON 字段不被接受,使用不带值的 gh pr list --json,它会打印 gh 支持的字段列表。
  • 每个 PR 会关闭哪些 issue:使用同一次调用返回的 closingIssuesReferences,不要从正文中搜索 Closes #N。这是 GitHub 自己解析的关联关系,因此可覆盖任意大小写形式的 Closes / Fixes / Resolves,以及通过 UI 手动关联的 issue,也不会被代码块或引用的审查评论中的相同字样误导。唯一例外是堆叠层:GitHub 会按设计将字段留空,此时适用分层回退方案:上方的调用已经包含 baseRefName,因此将其与默认分支比较;若 PR 未通过此项检查,则使用 gh pr view <n> --json body --jq 从正文提取 Closes #N,确保正文不会进入上下文。此类条目的 Closes 单元格应打印 issue 编号后加上 (stacked),让读者知道关联尚待确认,而非不存在;并照常从中传递 priority 和杠杆效应,处理方式与已解析字段相同。
  • 待审查集合:所有仍在等待审查的未关闭非草稿 PR(reviewDecision 为空或为 REVIEW_REQUIRED),按编号 + 会关闭的 issue + priority + unblocks 计数 + CI 状态 + 作者 + 当前由谁处理 + updatedAt + 标题的顺序保留,因为编号和它所对应的待完成工作应并列显示;两者合起来才是这条记录值得关注的全部原因。与未阻塞集合一样,按 priority 降序、unblocks 降序、最近更新时间排序。
  • PR 的 priority 取其会关闭的 issue 中最高的 priority,这与通过 closingIssuesReferences 将杠杆效应传递给 PR 的方式相同,原因也相同:PR 本身没有独立的重要性,只有它所完成工作的优先级。取最高值而非平均值,因为合并 PR 会完成所有这些 issue,而实际等待中的是最紧急的那个。不会关闭任何 issue 的 PR 没有 priority,因此打印破折号,按杠杆效应和更新时间排序。仪表板会将这些条目打印为表格,因为“有 3 个 PR 等待审查”并不能说明哪个需要你催促、哪个需要别人回复。
  • 当前由谁处理:根据审查人判断,绝不根据作者判断。 按此顺序检查三种情况:你出现在 reviewRequests 中 → 由你处理,去审查;其他人出现在 reviewRequests 中,或非作者出现在 latestReviews 中 → 由对方处理,注明姓名,表示你确实在等待;两者都不满足 → 无人审查,这是一个伪装成待审查 PR 的卡住 PR。第三种情况涵盖了所有个人仓库中的 PR,以及团队仓库中常见的遗漏(你打开了 PR,却没请求任何人审查)。两者的情况都一样:除非你采取行动,否则不会有人审查,因此这三种情况中只有这一种需要排序。
  • 是否有人能够审查? 仅当出现第三种情况时才检查,并且每次运行只检查一次:gh api repos/{owner}/{repo}/collaborators --jq 'length'。协作者恰好为 1,证明没有其他审查人,因此应直接由自己审查。人数超过 1,或遇到 403、错误、任何无法获取结果的情况,都意味着无法排除有审查人,因此行动建议应包含两种选择(“请求审查人,或自行审查”)。没有 PR 需要检查时,绝不调用此命令;调用失败也绝不应导致条目丢失:即使没有这项检查,“当前由谁处理”一列仍然正确,此探测只会让建议措辞更精准。
  • 跟踪器过时信号,一项低成本交叉检查:有多少已合并 PR 关联的 issue 仍处于未关闭状态。只统计数量,仅用于判断“对账”是否需要排序。绝不列出具体是哪项或原因,因为那是 issuekit 的工作。 计划(文件系统,列表始终会运行,未归档检查需要跟踪器):
  • 列出规范格式的 docs/plans/NNNN-plan-<slug>-YYYY-MM-DD.md 文件,以及不带序号的旧格式 plan-<slug>-YYYY-MM-DD.md。(如果仓库将计划存放在其他位置,则以仓库实际位置为准;若有 rfcs/、specs/ 或文档中说明的位置,则优先采用。)列表无需额外成本,始终会运行;阶梯中的计划级别会读取它。
  • 仅当仓库确实通过 GitHub issue 跟踪工作时,才计算未归档集合。 将每份计划与 issue 列表交叉核对,保留从未成为 issue 的计划。匹配时使用 --state all,而不是调查其他部分使用的开放 issue 查询:gh issue list --state all --json number,title --limit 200,只调用一次,且仅在存在计划文档时调用。一份几个月前已交付的计划对应的 issue 可能已经关闭,因此只匹配开放 issue 会把每份已完成的计划都报告为未处理;这正是值得抑制此面板的原因。
  • 同一次调用属于跟踪器解析的第 3 级,因此不会增加额外成本。 只有跟踪器读取得到存在的结果,未归档比较才有意义;若跟踪器缺失、未知或不可用,则跳过,绝不将计划报告为未归档。查询出错属于未知,不代表不存在。许多项目通过 Linear、Jira、TODO.md 或某个人的记忆来跟踪工作;如果调查在这类项目中宣称“有 18 项未归档”,那是在把自身盲点当成发现,还会引导用户对他们有意不使用的跟踪器运行 issuekit create。
  • 根据计划的 slug 和标题进行匹配;如果匹配存在不确定性,就视为已归档。 issue 标题与计划标题匹配、正文链接到计划路径,或 slug 匹配,满足其中任一项就足够。这种不对称是有意为之:此面板只会列出缺口,因此漏报只会少一行提示,而误报则会让用户重复登记已经跟踪的工作。
  • 未构建集合:没有跟踪器时,计划级别会据此排序。 查找以 Phase <n> 开头的标题,并宽松匹配分隔符(### Phase 2: auth 和 ### Phase 2 — auth 属于同一种格式,实际计划集合中两种格式都有)。如果阶段标题带有 (built YYYY-MM-DD) 时间戳,则该阶段为已构建;implementkit 会将其写入与 issuekit 的 (#41) 相同的末尾位置。两者可以共存,因此 ### Phase 2: auth (#41) (built 2026-08-20) 表示该阶段已跟踪且已交付。
  • 任何位置都没有时间戳的计划,不表示任何状态。 时间戳约定由每份计划自行选择是否采用,因此没有时间戳表示未标记,而非未构建;若将其视为未构建,就会把约定启用前编写的每份计划都报告为待办工作。将此类计划视为一个整体,并像仅使用 Git 的阶梯一样,直接将其整体选为优先项。一份计划一旦带有任意一个时间戳,该时间戳就具有权威性,其余未标记阶段确实属于未构建。带有完整时间戳的计划已完成,应予以移除。

评审标记(文件系统,无需跟踪器):

  • 待评审集合。 运行一次 grep -rl '^Review: pending' docs/。文件中会有一行单独写着标记 Review: pending,评审完成后则写入 Review: done <date>。commitkit 会写入这两个标记。每条匹配结果保留文件名和标题(第一个标题),并按序号从低到高排序。若 docs/ 目录不存在,或 grep 未匹配到任何内容,则不报告发现。
  • 此处只读取当前工作树。 另一个分支中提交的标记在切换到该分支之前不可见。不要提及它,因为调查无法得知自己没有读取到的内容。
3. 对优先完成的一项行动进行排序和选定

将信号映射到候选行动,并为每项标注所属的 kit/命令,然后选出适用级别最高的一项。同一级别内的并列情况按该级别自身的行说明进行处理;若未说明,则优先选择最近活动的项目,其余项目作为备选。根据 GitHub 信号是否可用来选择阶梯。 仅使用 Git 的阶梯(无 gh):

#状态下一步 →
1功能分支上有未提交的工作继续,或运行 commitkit
2有未推送的提交git push
3有一个暂存使用 gitkit rescue 检查并恢复,或将其删除
4有一个尚未合并的本地功能分支完成它,或使用 gitkit clean 清理它
4b有一份标记为 Review: pending 的文档阅读文档,然后使用 commitkit 将其标记为已审阅
5磁盘上有一份计划文档;由于没有跟踪器可供检查,无法确定它是否已归档使用 implementkit 实施最新计划
6位于基础分支上,工作区干净,没有待处理事项开始做某件事(最新计划),或运行 plankit
7触发了 CONTEXT.md 信号如果文件缺失,运行 domainkit init;如果内容已过时,运行 domainkit audit

完整阶梯(可用 gh),其中每种仅使用 Git 的状态在下方都有明确的归属。(会显示,但不会成为首选:已批准且 CI 通过的 PR;确实有其他人欠你的 PR。)

#状态下一步 →
0 †有一个可推进的 critical 问题,处于开启状态、未受阻,且尚未成为首选事项放下手头工作:如果状态为 ready 或可启动的 stacked,运行 issuekit start <N>;如果状态为 in-progress,则恢复处理
1你的 PR CI 未通过或收到修改请求修复 CI,或使用 mergekit fix <N> 处理审查意见
2你的 PR 无人审查(按优先级、然后按 unblocks、最后按最近更新时间排序)使用 mergekit start <N> 设置为自行审查,或请求审查者
3 †你当前所在分支对应的问题处于进行中 (未提交的工作也归入此项,作为“继续”处理)恢复处理,或运行 implementkit
4孤立的工作:基础分支上或未跟踪分支上的未提交工作,或未推送的提交运行 commitkit,或推送
5有一个暂存使用 gitkit rescue 恢复它以完成工作;如果已过时,则将其删除
6有一个尚未合并的本地功能分支完成它,或使用 gitkit clean 清理分支及其工作树
7 †触发了跟踪器过时信号使用 issuekit sync 对齐状态
8 †有一个 ready 问题,或一个可启动的 stacked 问题(按优先级、然后按 unblocks、最后按最近更新时间排序)运行 issuekit start <N>(通过 gitkit 创建工作树),然后运行 implementkit
8b**没有跟踪器:**最新计划中尚未构建的下一个阶段使用 implementkit 构建
8c †有一个 needs-planning 问题(按优先级、然后按最近更新时间排序)使用 grillkit 深入梳理,然后使用 issuekit triage 提升其状态
9 †有一个未标记的问题,或其状态不在生命周期映射中,需要分类使用 issuekit triage 对其分类
10 †有未评估的待办事项,即没有优先级标签的开启问题使用 issuekit triage 为其排序
10b有一份标记为 Review: pending 的文档阅读文档,然后使用 commitkit 将其标记为已审阅
11有未归档的计划 (仅当使用跟踪器时),或完全没有计划运行 issuekit create,或运行 plankit
12触发了 CONTEXT.md 信号如果文件缺失,运行 domainkit init;如果内容已过时,运行 domainkit audit

† 表示仅在使用跟踪器时才会触发的阶梯项。 排序前,请根据确定跟踪器确认是否使用跟踪器,因为其中七个阶梯项取决于此。使用其他方式跟踪工作的项目会直接跳过所有这些阶梯项,这正是第 8b 项所填补的空缺:没有它,阶梯就会到此为止,不会选出任何首选事项;对于磁盘上有尚未构建计划的仓库来说,“没有下一步”意味着调研失败,而不是得出结论。PR 和 Git 阶梯项(1、2、4、5、6、12)从不依赖跟踪器,因为无论使用什么跟踪器,分支和拉取请求都是相同的事实。 第 8b 阶是第 8 阶的无追踪器版本,而且它刻意处于相同高度。 两者都是开始某项工作的阶,两者都表示上方的完成类阶没有结果,而且选定工作后,两者都会以相同方式移交。它按照计划自身的顺序排序,也就是最新计划中编号最小且尚未构建的阶段,因为计划中的阶段按依赖顺序编写,跳过前面的阶段就可能导致某个阶段在其尚不存在的前置条件上构建。

stacked issue 的前置条件对应的 PR 仍处于打开状态且构成一条链时,它就可以开始处理;查看打开的 PR 时已经能看到这一点,因此无需额外调用。前置 PR 已合并或关闭的 issue 属于追踪器状态偏差:将它列在 Issues 行,并交给 issuekit sync 处理,而不是交给 start,否则后者会拒绝处理。第 8c 阶低于所有可开始的 issue,因为在人工确定决策之前,任何人都无法开始处理 needs-planning issue;它又高于分类阶,因为该 issue 已经完成分类。这一步需要人工进行深入讨论,因此只有在上方没有任何阶触发时,才会将它列为首选。

第 0 阶编号为零,因为它其实不算一个阶。 它是完成优先主阶序列中唯一有文档记录的覆盖项,若在序列中给它编号,就会让它看起来像一种只是恰好排在最前面的普通状态。它很少触发,而且必须指出它取代了什么;它下面的所有阶才是真正的阶梯。如果第 0 阶在大多数运行中都触发,那 critical 就失去了意义,真正该做的是 issuekit triage。

在两套阶梯中,CONTEXT.md 阶都低于其他所有阶(没有 gh 时为第 7 阶,有 gh 时为第 12 阶)。术语表跟不上代码,会让下一个 Agent 少一些词汇知识,但不会导致构建失败或 PR 卡住,因此只有在仓库中没有其他待处理事项时,才会将它列为首选。未安装 domainkit 时,简单的做法是“手动更新 CONTEXT.md”。

第 10 阶低于所有可执行阶,高于“去规划点什么”。 未排序的待办事项确实是个缺口,因为上方的事项都无法正确安排顺序,但它仍属于追踪器维护,而不是实际工作,因此它绝不会排在用户能够真正完成的事项之前。它之所以能占一阶,是因为如果没有这一阶,一个无人设置任何优先级的仓库就会永远按杠杆值排序,却不会有人说明原因。

第 10b 阶(没有 gh 时为第 4b 阶)紧挨着规划阶之前。 已评审的计划是下一步工作的输入,因此评审应先于提交计划或开始构建。它低于所有能完成实际工作的阶,因为待处理的评审不会阻挡任何 PR 或 issue。若有多个文档待处理,将序号最小的列为首选,并将其余文档逐一列为候补项。盖章无需追踪器,因此无论追踪器处于何种状态,这一阶都会触发。

第 11 阶的前半部分仅在计算出未提交集合时才存在,也就是说,解析结果为使用追踪器。如果仓库在其他地方追踪工作,statuskit 就无法判断某个已提交计划与未提交计划的区别,因此不会断言某个计划未提交:这一阶就只剩下后半部分,完全没有计划 → plankit。在一个把工作提交到其他地方的项目中,将“提交你的计划”排在前面,比保持沉默更糟糕,因为这是一条基于从未进行过的读取而给出的笃定建议。 第 1 和第 2 级其实是同一个问题:你自己的 PR 卡在了你这里。 红色 PR 明显地卡住了,尚未评审的 PR 则悄无声息地卡住了。沉默的那种会搁置数周,因此它的优先级高于恢复一个只完成了一半的问题,而不是排在它后面:代码已经写好并通过检查,所以只需最少的努力就能完成最多的工作,这正是先完成未竟之事的全部意义。这是唯一一个在影响力相同的情况下打破平局、要求你完成而非开始的级别,因为无需重新切换回其他上下文:评审已完成的 PR,无论你选哪一个,工作量都相同,所以平局时不妨选能释放最多资源的那个。

如果未安装对应的工具包,就写出具体操作(例如写“提交你的更改”,而不是“运行 commitkit”;对于已评审的文档,写“将标记改为 Review: done <date>”),因为 statuskit 负责路由,而且不要求使用该生态系统。

4. 输出:先显示仪表板,再突出一个首选操作

按照下方格式并遵循呈现规则打印仪表板,然后列出按优先级排序的下一步操作,并将 第 1 项操作加粗,同时注明对应的工具包/命令。表格包含了单纯计数无法展示的细节:使用跟踪工具时,表格会列出未受阻的问题、等待评审的 PR,以及注明阻塞原因的受阻问题;未使用跟踪工具时,两个问题表格没有内容可列,此时由尚未构建的阶段取而代之。内容控制在一屏内:

# Project status · <repo> · <branch> · YYYY-MM-DD

## Working tree  <clean | N uncommitted · M unpushed · stash K>

## Issues        in-progress N · ready N · in-review N · blocked N     (omit without gh, or without a tracker)

Unblocked (N) · highest priority first
| Issue | Priority | Unblocks | Status | Last active | Title |
|---|---|---|---|---|---|
| #12 | critical | 3 | ready | 2d | <title> |
| #31 | high | 1 | in-progress | 4h | <title> |
| #47 | none | 0 | unlabeled | 3w | <title> |

## Pull requests <open N: X awaiting review, Y CI-red, Z ready to merge>   (omit without gh)

Waiting for review (X) · highest priority first
| PR | Closes | Priority | Unblocks | CI | Author | Next move | Last active | Title |
|---|---|---|---|---|---|---|---|---|
| #34 | #12 | critical | 3 | ✓ | you | nobody reviewing → yours | 1d | <title> |
| #29 | #19, #23 | high | 0 | ✗ | @someone | yours | 6h | <title> |
| #38 | none | none | 0 | ✓ | you | theirs: @reviewer | 2w | <title> |

Blocked issues (N)
| Issue | Priority | Waiting on | Title |
|---|---|---|---|
| #19 | high | #12 | <title> |
| #23 | low | `blocked` label, no blocker named | <title> |

## Plans         <M unfiled: plan-debugkit, plan-testkit>   (omit entirely unless there is a finding)

Unbuilt phases (N) · plan order      (only when there is no tracker, and a plan carries stamps)
| Plan | Phase | Title |
|---|---|---|
| plan-sso-login | 3 | <phase title> |
| plan-sso-login | 4 | <phase title> |

## Review        <N pending: plan-sso-login, research-auth-providers>   (omit entirely unless there is a finding)

## Next move
**→ <the #1 action>.** Run `<kit / command>`.

Then:
- <runner-up> · `<kit / command>`
- <runner-up> · `<kit / command>`
- <runner-up> · `<kit / command>`

每条操作都使用程序式表达。 首选操作、备选操作和快照中的复选框列表,都要让人一眼就能看懂,以便决定接下来处理什么。因此,请使用 ASD-STE100 简化技术英语:每行一条指令,使用主动语态和现在时,明确指出执行者,不用隐喻,也不用有歧义的词。写“合并 #34”和“归档待办事项”,不要写“推动 #34 过关”。整个仪表板中,每个对象始终使用同一个术语,因为某条操作称其为计划文档,而某个面板称其为未归档计划,会让人以为它们是两个不同的对象。这条规则同样适用于打印出的仪表板和快照文件,这样才能让人快速浏览这段内容,而不必逐字阅读。

呈现规则

所有关于打印内容、位置和顺序的规则都列在此表中。快照文件也遵循相同的规则。

元素规则原因
状态面板Working tree、Issues、Pull requests、Plans 和 Review 均将标题和计数放在同一行,后面只跟一个表格。移动原因写在移动行中。读者开始阅读前,用四行就能了解项目进展。面板若再加一句话,就会变成报告。
面板是否显示Working tree、Issues 和 Pull requests 始终显示,包括计数为 0 的情况。仅当数据源不可用时才省略面板:没有 gh 时省略 Issues 和 Pull requests;没有跟踪器读取结果时省略 Issues。原因只说明一次。干净的工作树和空的 PR 列表都是值得确认的事实;固定的面板集合也能让不同时期的快照保持可比。
Plans 面板仅在发现问题时显示:有跟踪器读取结果时显示未归档的计划;没有跟踪器时显示带有标记的计划中尚未构建的阶段。两种情况可以同时显示。没有发现时,不显示 Plans 行,不在文件中显示 ## Plans 小节,也不提及原因。空的计划计数(21 filed · 0 unfiled)无法采取行动,而其他所有面板都报告始终存在的状态。Review 同样是有条件显示的,只有文档带有 Review: pending 时才显示。Plans 和 Review 是仅有的条件面板。
Review 面板仅在发现带有 Review: pending 标记的文档时显示。只显示一行计数和文档名称,不显示表格。没有发现时,不显示 Review 行,也不在文件中显示 ## Review 小节。该面板报告标准面板集合无法显示的待处理项,而空队列无法采取行动。
额外面板最多一个,用于标准面板集合无法显示的一类正式队列(如 IDEAS.md 中的待办事项或 RFC 索引),内容取自调查时读取的文件。绝不添加通过运行构建、测试或 lint 填充的面板。statuskit 的调查只读,而固定的面板集合才能让不同时期的文件保持可比。
表格顺序依次为 Unblocked、Waiting for review,然后是 Blocked issues (N),最多同时显示三个。Blocked issues 放在 Pull requests 面板下,并保留完整名称。Unbuilt phases 放在 Plans 下。面板顺序始终不变。读者会在第一行可以采取行动的内容处停下,因此所有可采取行动的行都应排在第一条无法采取行动的行之前。脱离所属面板时,单独的 Blocked (N) 会被理解为被阻塞的 PR。
in-review issue在 Waiting for review 中显示为一行,绝不放在 Unblocked 中。其计数保留在 Issues 行上。没有开放 PR 的条目要在 Issues 行上注明(in-review 7 · 1 with no open PR),并转交给 issuekit triage。PR 行会列出负责人和 CI 状态。将 issue 移回 Unblocked 会让人误以为可以着手处理。
行列出所有符合条件的行。超过 10 行时,最多显示 10 行,并以 +N more 和用于显示其余内容的 gh 命令结尾。完整性是重点;悄悄截断会让人以为列表完整。
空表格移除表格,保留计数行(Waiting for review (0))。0 是调查得出的事实,不代表缺少面板。
排序Unblocked 和 Waiting for review 按 Priority、Unblocks、最近活动排序,并在计数行中注明排序方式(· highest priority first;如果省略 Priority,则为 · highest leverage first)。Blocked issues 按最近活动排序,保留 Priority,但不显示 Unblocks。Last active 是一列(4h、2d、3w),不用于排序。下一项要处理的行应位于第一行;声明的排序方式也应能通过列进行核对。被阻塞的行无法着手处理,因此没有地方体现其杠杆作用;但其优先级可以说明是否值得追查阻塞原因。
列顺序issue 表中,排序键紧跟 ID;PR 表中,排序键紧跟 Closes。上下文列按使用频率递减排列。PR | Closes 这一对列能让 PR 行一目了然。
Closes 单元格PR 未关闭任何内容时显示 none,绝不留空。堆叠层抓取到的链接显示为 #12 (stacked)。none 提醒读者合并后 issue 仍会保持开放;留空则会被理解为“尚未检查”。
Next move 单元格yours、theirs: @name 或 nobody reviewing → yours。写出审查者姓名后,这项声明便可以核实。
删减规则所有行的作者相同时,删去 Author(在计数行中注明 all yours);所有 Unblocks 值均为 0 时,删去 Unblocks;没有任何行带优先级时,删去 Priority。如果表格仍放不下,就将 Title 截为开头几个词。绝不删去排序键。值始终不变的列会让人误以为相关事实已经核实。删减可以让九列的 PR 表格显示在一个屏幕内。
移动行每个候选项占一行,准确注明一个 issue 或 PR,并与快照复选框保持相同的分类。打印的列表与文件中的内容逐项一致。
5. 撰写状态快照:这是默认操作,不是一个提议

每次运行都写入文件。 终端仪表板会滚动消失,而且排好优先级的行动项无法逐一勾选;同样的内容写入磁盘后更易阅读,也能兼作本次运行的待办清单。所以不要征求许可:直接写入,然后用一行说明文件位置:

已保存到 docs/status/NNNN-status-<repo-slug>-YYYY-MM-DD.md · 临时文件,已加入 gitignore,未提交。

如果写入规则跳过了 .gitignore 条目,则用 untracked 代替 gitignored。

只有用户要求时才跳过。 “只打印出来”“不要文件”“什么都别写”“只在屏幕上显示”“/statuskit --no-file”都表示本次运行应遵照要求,只打印仪表板。跳过仅适用于本次运行;除非用户明确提出,或仓库的 Agent 指南文件(CLAUDE.md 或同等文件)有此要求,否则不视为长期偏好。若没有可写入的文件系统(见下文),也静默跳过。

保存位置。 docs/status/NNNN-status-<repo-slug>-YYYY-MM-DD.md,使用下一个序号、简短的小写 kebab-case slug(通常为仓库名称;如果快照只涵盖项目的一部分,则使用更具体的名称,例如分支或 issue),以及 ISO 创建日期。要获取序号 NNNN,请查看当前工作树、git worktree list 列出的所有其他工作树,以及 origin/HEAD(执行 git fetch origin 后运行 git ls-tree --name-only origin/HEAD docs/status/)中的 docs/status/,取最前面的四位数字序号中的最大值,再加一;如果不存在,则从 0001 开始。扫描这三个来源,以免并行工作树取得相同序号。如果某个来源不可用,例如没有远程,则跳过该来源;没有 git 时,只列出目录内容。序号按目录计算,永不重复使用。如果 docs/status/ 不存在,则创建它。

每天一个文件,始终更新,绝不新增。 写入前,列出 docs/status/,查找是否已有日期为今天的快照。如果存在,就更新该文件,并保留原文件名,即使本次运行选出的 slug 不同也一样。只有当目录中没有任何日期为今天的文件时,才创建新文件。状态文件是某一时刻的记录;同一个下午出现三份这样的文件,只会让临时目录变成考古现场,更糟的是,用户勾选的待办会分散在多个看起来都像最新的文件里。如果今天的快照确实涵盖单一代码仓库中的不同项目,则使用该项目专属的 slug,并按 slug + 日期匹配;同一个项目一天内绝不会有两个文件,因此绝不能退而使用序号后缀。

更新意味着合并,而非覆盖。 根据 git 和 GitHub 重新梳理完整情况,绝不以文件现有内容为准;然后只按行动项的键(见下文)匹配,将仍未完成的行动项中所有已勾选的状态保留下来。其他内容都根据最新梳理结果重写:即使措辞完全变了,只要键相同,仍然是同一个行动项;即使措辞碰巧没变,只要键不同,就是不同的行动项。已勾选但不再适用的行动项移至 Done today;未勾选且不再适用的行动项直接删除。

文件内容。 与打印出的仪表板相同,但增加以下两项:

  • 一行来源信息,记录快照的创建时间、对应的提交,以及今天已重写的次数(Snapshot: 2026-07-23 14:20 · <branch> @ <short-sha> · run 3 today (first 09:05))。否则,过期文件会看起来像当前快照;没有运行次数,下午的重写也无法与早上的初始版本区分;
  • 将排好优先级的行动项写成复选框列表,让文件可以作为待办清单使用;优先级最高的行动项排在最前,并为每项附上其工具包/命令:
## Next moves

- [ ] **<the #1 move> (critical, unblocks 3)** · `<kit / command>` 
- [ ] <runner-up> (high, unblocks 1) · `<kit / command>` 
- [ ] <runner-up> · `<kit / command>` 

## Done today

- [x] <move, as it read when it was ticked> 

## Surfaced, not queued

- #34 approved + CI-green · merge when you're ready (`mergekit close 34`)
- #29 awaiting @someone's review

每个行动都带有一个键。 末尾的 `` 注释是合并时匹配的依据;之所以需要它,是因为无法匹配可见文本:措辞每次运行都会重新生成,因此在调查后仍保留的行动会以不同措辞再次出现,其勾选状态也会悄无声息地丢失。带有 issue 或 PR 编号的行动比较容易处理;没有编号的行动,例如配置标签或记录待办事项,正是文本匹配会失败的地方,也正是用户的勾选状态最需要保留的地方。渲染时看不到这个键,因为文件是给人看的,而且键在文件之外毫无意义。

键必须来自固定词汇表,绝不能临时拼出一个 slug,否则键也会像正文一样每次运行都发生变化:

行动的对象键
一个 issueissue-12
一个 PRpr-34
一份计划文档plan-<slug>,即计划本身的 slug
计划中的一个阶段plan-<slug>-phase-<n>
一份待审核的文档review-<name>,即去掉序号和日期后的文件名,例如 review-plan-sso-login
一个本地分支branch-issue-12-retry-budget
一个 stash 条目stash-<sha>,即通过 git stash list --format='%h' 获取的 stash 提交短 SHA;新推入 stash 后,stash@{0} 这样的索引会发生变化
没有具体对象的阶梯行动每个阶梯固定使用一个 slug:push、reconcile、triage、prioritize、repo-labels、declare-tracker

释放工作量的行动要说明这一点,用户排过优先级的行动要先说明优先级。 如果排队中的行动优先级高于 medium,或 unblocks 数量大于零,就把两者都写在对应行中:**Start #12 (critical, unblocks 3)** · \issuekit start 12`。用户实际做选择的地方是复选框列表,往往是在表格滚动过去数小时之后;这两条信息就是说明该项为何排在下一项之前的全部理由。某条信息没有意义时就省略:不要写 unblocks 0,也不要写 medium` 或留空,因为读者本来就默认如此,或知道没有这条信息。两者都存在时,优先级写在前面,与排序方式一致。

键不能离开这个文件。不要把它写进提交消息、分支名、issue 正文或其他任何地方:它只是两个版本的同一个被 gitignore 的临时文件之间的关联键;如果把它导出到永久历史中,就会让持久产物引用一个临时文件。真正应该进入 git 的关联信息已经存在了,即 PR 上的 Closes #12,而调查无论如何都会读取它。

每个行动都必须有一个能将其标记为完成的信号。 排队中的行动应该是下一次调查能够观察到已完成的事情:PR 已合并、issue 已关闭、标签已存在、工作树已干净。完成状态通过这些方式检测,而不是看勾选状态;勾选只是一条用户在当天中途写下的注释,这就是合并时必须保留它、也绝不能把它当作证据的原因。没有可观察信号的行动(“决定这个仓库是否使用自己的工作流”)永远不会自行移出列表,因此每次运行都会重新排上优先级,唯一能让它消失的,是当天的文件带着它一起被丢弃。这些不是下一步行动,而是决策;因此应交给 plankit 处理,或使用 issuekit create 创建 issue,然后让生成的 issue 出现在这里。如果你说不出什么情况会让某个行动消失,它就不该出现在列表中。

已勾选的行动要放进 Done today,而不是扔进垃圾堆。 如果新的调查不再支持用户已勾选的行动,这表示该行动已经完成,所以应将它记在 ## 今日完成 下,而不是像其他过时的阶梯行动那样删除。每天一个文件,只有在内容随着当天进展不断累积时才有意义;如果文件只显示尚未完成的事项,那么下午 6 点看到的内容和上午 9 点完全一样,而状态文件绝不能给人这种印象。如果当天没有任何完成事项,就完全省略这一节。 每个复选框只对应一项任务,绝不合并。 每一项都是用户可以独立完成并勾选的一件事,因此必须且只能对应一个 issue 或 PR。“用 issuekit start 开始处理 #12、#19 和 #23”是三项,不是一项;“对 4 个未加标签的 issue 进行分类”也一样。如果阶梯中的某一级适用于多个 issue,就拆成每个 issue 一项,每项都附上该 issue 自己的编号、标题和命令,并按该级中的顺序排列。快照采用复选框列表,原因就在于未完成一半的事项不可见:一个框涵盖三个 issue,必须等三个都完成才能勾选;在此之前,它看起来就像什么都没发生。同一规则也适用于 Surfaced, not queued 列表:每个 PR 单独一行,绝不写摘要行。如果拆分后列表变长,那才是工作的真实长度;像表格那样限制列表长度,按最近更新优先,然后添加一行 +N more,不要再把事项合并起来。

所有三个表(未受阻、等待审核、受阻的 issue)都要按原样写入文件,并保持上述顺序。它们是快照中会逐渐变成工作清单的部分;如果文件只保留计数,那就比它取代的终端输出还糟。除了文件自身新增的内容之外,不要把它扩写成仪表板中没有的报告:采用相同的调查范围、相同的一组已关闭面板,并以持久化形式呈现。

这是临时文件。 该文件是草稿,不是受跟踪的产物,因此不要提交。只有用户明确要求时才提交;既然这是用户的决定,就应尊重,不要争辩。

写入规则

statuskit 只写入本地文件,下表列出了全部写入操作。这里的任何内容都不会到达远程端、分支或跟踪器。

写入内容适用时机条件
快照,docs/status/NNNN-status-<slug>-YYYY-MM-DD.md(一次 Write)每次运行都执行,除非用户要求跳过,或没有可写入的文件系统。若 docs/status/ 不存在,则创建它。无。在已保存说明中写明文件保存位置。
向根目录 .gitignore 追加一行 docs/status/(一次 Edit)仅在创建首个快照之前,且根目录存在 .gitignore,并且 git check-ignore -q docs/status/x.md 检查失败时执行。如果根目录没有 .gitignore,则不要创建:快照保持未跟踪状态。无。在已保存说明中写明此操作。
向现有 Agent 指南文件追加一条声明语句(一次 Edit)仅在 声明提议 中,针对空数组的未知读取结果执行。预览并获得用户同意。

没有文件系统? 将快照以代码块形式输出,并附上规范路径 docs/status/NNNN-status-<repo-slug>-YYYY-MM-DD.md;如果无法列出用户的快照,则使用 0001,以便用户自行保存。

备注

  • 任何面向外部的内容都不会改变。 statuskit 负责调查并提供建议;它绝不触碰 git 或 GitHub 状态。如果建议需要进行此类修改,它会将任务转交给负责的工具包,由该工具包自行预览并征求批准。写入规则列出了 statuskit 写入的所有文件:每次运行都会写入快照、首次写入快照前会在 .gitignore 中添加一行,以及仅在获得批准后才会添加一条声明。所有这些都不会到达远程服务、分支或跟踪器,这正是 statuskit 可以随时安全运行的原因。应这样描述边界,而不是说“零修改”,因为快照始终会写入;一个与技能实际行为相矛盾的醒目说法,远不如一个范围更窄但准确的说法。
  • 只转交,不启动。 转交意味着指出工具包名称及其单行命令,因为 statuskit 不会替你调用工具包;由用户启动它。先说“运行 issuekit sync”,然后又亲自调用该工具包,就会在说“帮我了解情况”的同时重新开始修改操作,破坏只读立场。
  • 只转交,不设门槛。 如果未安装相应工具包,每条建议都会退化为一条普通命令。即使是只有 git 的裸仓库,statuskit 也有用。
  • 坚守 issuekit 的界限。 显示问题计数、按 ID 列出未阻塞的问题、列出被阻塞的问题及各自等待的事项、列出已准备好/正在进行的问题,并显示每个问题声明的优先级;计算一个是否过时的布尔值,用于决定“协调”的排序。列出 ID 并未越界,因为这只是把同一项读取结果以实用的方式展示出来,也能省去在采取行动前先通过 gh 查询一轮。issuekit 负责的是对跟踪器的判断:绝不逐项给出健康状况结论;一旦开始解释哪些问题已过时以及原因,就该由 issuekit 的 triage/sync 处理,statuskit 应指向它,而不是代为处理。
  • statuskit 读取优先级,但绝不分配优先级。 显示问题所带的标签,和读取其他事实一样;按标签排序正是标签的用途。为尚未评级的问题推断优先级则不然,因为这是属于 issuekit triage 的跟踪器判断,也是这份概览可能悄悄捏造其声称只是在报告的信息的唯一地方。未评估的问题在仪表板上仍保持未评估,排序低于 low,并被转交处理,而不是靠猜测。
  • gitkit 负责 git 事实。 基础分支、分支命名约定以及工作树的位置都由 gitkit 提供,statuskit 负责读取并报告。在这里重复保存任何一项信息,都会让仪表板开始信誓旦旦地描述一个已与其记录不符的仓库。
  • 这里的 Edit 只用于追加两处内容,除此之外别无用途:.gitignore 中的 docs/status/ 行,以及 Agent 指南文件中的声明句。快照使用 Write。在强制要求配置该字段的主机上移除此工具后,两者都会各自退化:快照仍会保持未跟踪状态,而声明提议会打印出供用户放置的那一行。
  • 工具列表中的 Skill 只供 gitkit 使用,除此之外别无用途。 鉴于上面的“只转交,不启动”规则,它看起来似乎可以移除,所以值得说明:statuskit 在调查期间会调用 gitkit,以获取基础引用、分支命名模式和工作树路径。它在操作说明中提到的其他工具包,都只会被转交任务,绝不会被调用。移除该工具后,调查就会悄悄开始猜测基础分支是 main。
  • 按需运行,不留状态。 每次运行都是一次全新的读取:statuskit 不会在仓库根目录保留 STATUS.md,也不缓存上次运行的结果;它绝不会读取快照来缩短调查流程。它会从现有文件中获取的唯一信息,是哪些方框已被勾选;调查本身始终会根据 git 和 GitHub 重新推导。docs/status/ 文件是提供给人类(或下一个 Agent)的输出,并非 statuskit 会信赖的记忆。

评论

支持 Markdown