issuekit
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chineseissuekit
issuekit
Own the GitHub issue lifecycle through the CLI, in five explicit modes:
gh- . Turn a plan document or a plain description into well-formed issues, with parent→child links.
create - . Take a
startissue into its own worktree and flip itready.in-progress - . Once its PR has merged, close the issue, unblock what it was holding up, and tear the worktree down.
close - . Reconcile and repair the PR↔issue relationship after the fact (issues a merged PR should have closed, a missing link on an existing PR, an un-ticked parent checklist).
sync - . Report the health of the tracker, then offer fixes you approve.
triage
One skill, five jobs, because they're the same job at five points in a dev workflow: file the work, pick it up, land it, keep everything in sync as PRs merge, and keep the tracker honest.
closesyncclosesyncclosesync通过 CLI掌控GitHub issue生命周期,包含五种明确的模式:
gh- (创建):将规划文档或普通描述转换为结构规范的issue,并建立父→子issue关联。
create - (启动):将标记为
start的issue转入专属工作树,并将其状态切换为ready。in-progress - (关闭):当对应的PR合并后,关闭该issue、解除其阻塞的依赖项,并清理对应的工作树。
close - (同步):事后协调并修复PR与issue的关联(比如PR已合并但issue未关闭、现有PR缺失关联链接、父issue的 checklist 未勾选等情况)。
sync - (梳理):报告追踪器的健康状态,然后提供经你批准的修复方案。
triage
一个工具,五种功能,因为它们是开发工作流中五个节点的同一项工作:提交任务、接手任务、完成任务、PR合并后保持所有内容同步、以及确保追踪器信息准确。
closesyncclosesyncclosesyncWhen this fires
触发场景
The user wants to act on GitHub issues. Route to a mode from what they ask:
- create. "Create issues from this plan", "open issues for ", "file an issue for X", "file this as an issue".
plan-auth.md - start. "Start issue #42", "begin #42", "pick up #42", "spin up a worktree for #42", "I'm working on 42 now".
- close. "Close #42", "close out #42", "wrap up #42 now the PR merged", "tear down #42's worktree", "#42 landed, clean it up".
- sync. "Sync my issues", "this PR merged but the issue is still open", "link this PR to #42", "tick the parent checklist".
- triage. "Triage the backlog", "what's the state of my issues", "review open issues", "any stale issues", "prioritize my backlog", "set the priority on #42", "nothing has a priority".
If no mode is clear, ask first. Present the modes as options and let the user pick before doing anything, and don't guess between creating and mutating the tracker.
Worktrees and branches are gitkit's. and bookend a worktree's life, and both get it from gitkit, where the branch name, the path convention, create-or-adopt, and teardown all live. issuekit answers "is this issue workable, and what does the tracker say now?"; gitkit answers "where does the code for this branch live?" Neither reaches into the other's internals: issuekit hands gitkit an issue number and title, gitkit hands back a branch and a path.
startclose当用户希望对GitHub issue执行操作时,根据用户的请求匹配对应模式:
- create:“根据这份规划创建issue”“为创建issue”“为X提交一个issue”“把这个内容作为issue提交”。
plan-auth.md - start:“启动#42号issue”“开始处理#42”“接手#42”“为#42创建工作树”“我现在开始处理42了”。
- close:“关闭#42”“收尾#42”“PR已合并,完成#42”“清理#42的工作树”“#42已完成,进行清理”。
- sync:“同步我的issue”“这个PR已经合并,但issue还处于打开状态”“把这个PR关联到#42”“勾选父issue的checklist”。
- triage:“梳理待办事项”“我的issue状态如何”“审核打开的issue”“有没有过期的issue”“给我的待办事项排优先级”“设置#42的优先级”“所有issue都没有设置优先级”。
如果无法明确匹配模式,请先询问用户。列出所有模式供用户选择,在执行操作前不要猜测用户是要创建还是修改追踪器内容。
工作树和分支由gitkit负责。和构成了工作树生命周期的首尾环节,二者均依赖gitkit,分支名称、路径规则、创建或复用逻辑、以及清理操作都由gitkit管理。issuekit负责回答“这个issue是否可处理,以及当前追踪器状态如何?”;gitkit负责回答“这个分支的代码存放在哪里?”。二者互不介入内部实现:issuekit向gitkit传递issue编号和标题,gitkit返回分支和路径信息。
startclosePreflight (every mode)
前置检查(所有模式通用)
Before any GitHub call, confirm the tooling is ready:
sh
gh --version # gh installed?
gh auth status # authenticated?
gh repo view --json nameWithOwner -q .nameWithOwner # inside a repo?- If is missing or unauthenticated, say so and point to
gh/https://cli.github.com. Don't work around it.gh auth login - Invoking issuekit answers the question of whether this project uses GitHub Issues. Not every project tracks work here, and a skill that surveys a repo has to resolve that before it recommends anything. issuekit never does: someone asking to file, start, or close an issue has already said where the work lives. So files issues without first checking whether the project files issues, and no mode ever declines on the grounds that the repo looks like it tracks work elsewhere.
create - No shell or at all (e.g. a browser-based agent)? You can't call
gh. Instead do the reasoning from what the user provides and print the exactghcommands for them to run themselves: issue bodies as codeblocks, andgh/gh issue create …lines ready to paste.gh issue close …
Safety stance, for the whole skill. Creating, closing, relabeling issues and editing PR bodies are outward-facing mutations. Preview every mutation and get an OK before it runs, so nothing changes on GitHub unprompted. Never merge PRs.
One exemption, and it belongs to the mode, not the caller. 's flip runs without a preview, for every caller, meaning a person at the keyboard and an unattended orchestrator alike. It's the only mutation here that asks a question already answered twice over: the guard has refused everything a human hasn't grilled, and invoking is the instruction to start the issue. Flipping the label is what "started" means in the tracker, so a confirmation prompt buys nothing and costs the one thing exists to protect: an issue sitting in a worktree while the tracker still advertises it as free for someone else to pick up. Nothing else widens: still previews, still previews, and still preview every move, and no caller of any kind gets to skip the guard itself.
startready → in-progressreadystart <n>startcreateclosesynctriage在调用任何GitHub接口前,确认工具已准备就绪:
sh
gh --version # 是否已安装gh?
gh auth status # 是否已认证?
gh repo view --json nameWithOwner -q .nameWithOwner # 是否处于仓库目录下?- 如果未安装gh或未完成认证,请告知用户并引导其访问或执行
https://cli.github.com。不要尝试绕过该步骤。gh auth login - 调用issuekit即表明项目使用GitHub Issues。并非所有项目都在此处追踪任务,因此扫描仓库的工具需要先确认这一点才能给出建议,但issuekit无需如此:用户要求提交、启动或关闭issue时,已经明确了任务的追踪位置。因此模式会直接创建issue,无需先检查项目是否使用GitHub Issues,且任何模式都不会因仓库看起来在其他地方追踪任务而拒绝执行操作。
create - 完全没有shell或gh环境(例如基于浏览器的Agent):无法调用gh命令。此时需根据用户提供的信息进行逻辑推导,并打印出可供用户直接执行的gh命令:将issue内容放在代码块中,提供/
gh issue create …等可直接粘贴的命令行。gh issue close …
工具整体安全原则:创建、关闭、重新标记issue以及编辑PR描述均属于对外修改操作。所有修改操作都需先预览并获得用户批准后再执行,确保GitHub上的内容不会被无提示修改。绝不合并PR。
唯一例外,且由模式本身决定,而非调用者:模式下的标签切换无需预览,对所有调用者均生效,包括手动操作的用户和无人值守的编排器。这是唯一无需确认的修改操作,因为该操作的合理性已被双重验证:标签校验已拒绝所有未经过人工审核的内容,而调用本身就是启动该issue的指令。切换标签是追踪器中“已启动”的标志,因此确认提示毫无意义,反而会破坏模式最核心的作用:避免issue已处于工作树中,但追踪器仍显示其可被其他人接手的情况。除此之外的所有操作均需预览:仍需预览、仍需预览、和仍需预览每一步操作,且任何调用者都无法跳过标签校验本身。
startready → in-progressreadystart <n>startcreateclosesynctriagereadyTitle convention (every issue this skill creates)
标题规范(本工具创建的所有issue)
Issue titles follow the same shape as commitkit's commit subjects and the Conventional Commits specification, so the tracker and the git log read as one workflow. Format:
type(scope): short imperative summaryPick the from what the issue delivers, not the files it touches. The set mirrors commitkit's, with one addition () for parent issues:
typeepic| type | when |
|---|---|
| a parent issue that groups child issues/sub-issues |
| a new capability the user can see |
| a bug fix |
| documentation only |
| behavior-preserving code change |
| a performance improvement |
| adding or fixing tests |
| build system, deps, or pipeline |
| formatting/whitespace, no logic |
| routine maintenance that fits nothing above |
Rules, applied to every title you generate:
- is mandatory, naming the module, package, directory, or feature area the work belongs to (
(scope)). For genuinely global work (repo-wide config, tooling, cross-cutting cleanup) fall back tofeat(auth): …:repo.chore(repo): … - Entirely lowercase. Never capitalize any word in the title, including the first. Proper nouns and acronyms (,
OIDC,SSO) are the only exceptions.CI - Imperative mood, stating the effect ("add sso login"), not the activity ("changes to auth"). No trailing period. Keep it concise.
- A parent epic and its children share the scope so the group is obvious in the list: over
epic(auth): …,feat(auth): oidc login end to end.feat(auth): sso account linking
If the repo has its own issue-title style (visible in or an ), follow that instead and say you did; see Notes.
gh issue list.github/ISSUE_TEMPLATE/issue标题遵循与commitkit提交主题相同的格式,符合Conventional Commits规范,确保追踪器和git日志的工作流保持一致。格式:
type(scope): short imperative summary根据issue交付的内容选择,而非其涉及的文件。类型集合与commitkit一致,仅新增用于父issue:
typeepic| 类型 | 适用场景 |
|---|---|
| 作为父issue,用于分组子issue/子任务 |
| 用户可见的新功能 |
| bug修复 |
| 仅涉及文档修改 |
| 不改变功能的代码重构 |
| 性能优化 |
| 添加或修复测试 |
| 构建系统、依赖项或流水线修改 |
| 格式/空白修改,不涉及逻辑变更 |
| 不属于上述类型的常规维护 |
所有生成的标题需遵循以下规则:
- 为必填项,指定工作所属的模块、包、目录或功能区域(例如
(scope))。对于真正的全局工作(仓库级配置、工具、跨模块清理),使用feat(auth): …作为scope:repo。chore(repo): … - 全部小写。标题中所有单词均小写,包括第一个单词。专有名词和缩写(、
OIDC、SSO)除外。CI - 祈使语气,描述最终效果(例如“add sso login”),而非操作过程(例如“changes to auth”)。末尾无句号。保持简洁。
- 父epic及其子issue共享同一个scope,以便在列表中清晰识别分组:例如下包含
epic(auth): …、feat(auth): oidc login end to end。feat(auth): sso account linking
Lifecycle labels (every mode)
生命周期标签(所有模式通用)
issuekit tracks where an issue sits in the workflow with a small, flat set of status labels. It uses these labels and never creates them. Provisioning labels is the job of a companion skill, repokit. When a label this skill needs is absent from the repo, stop and tell the user how to add it (run , or the exact line) rather than creating it yourself or skipping silently.
repokitgh label createThe canonical map has exactly one status label active at a time, moving left to right through the workflow, with the three side-exits applying whenever they fit. This table is the shared contract with repokit, the skill that provisions these labels. Maintainers must keep the two tables aligned on names, colors, and meanings:
| label | color | means | typically set by |
|---|---|---|---|
| | filed, not yet assessed or broken down | create (ad-hoc), triage |
| | not yet specified enough to work; a human plan/grill session is still owed | issuekit create / afkkit gate |
| | specified and independent, safe to take into its own git worktree now | issuekit create |
| | has an unmet prerequisite; the blocker is named in the body as | issuekit create / sync |
| | actively being worked in a worktree | issuekit start |
| | a PR is open, awaiting review or merge | a PR-authoring skill / sync |
| | stalled pending more detail before it can proceed | triage |
| | will not be actioned | triage |
| | superseded by another issue | triage |
A closed issue needs no label, because the closed state is the signal.
donereadyblockedreadyblockedBlocked by #Ngh issue list --label readyneeds-planningreadyreadyneeds-planningreadygh issue list --label needs-planningreadyType lives in the title, not a label. Issues already carry / per the title convention, so this map has no labels, only lifecycle status.
feat(scope):fix(scope):type:When a needed label is missing, check once with , then report the gap instead of mutating around it:
gh label listLabelisn't in this repo. Provision the workflow labels with repokit, or add just this one:blockedgh label create blocked --color D93F0B --description "has an unmet prerequisite (see 'Blocked by #N' in the body)"
Apply a label only once it exists () and, like every mutation in this skill, preview it and get an OK first.
gh issue edit <n> --add-label <label>issuekit通过一组小型的扁平状态标签追踪issue在工作流中的位置。工具仅使用这些标签,绝不创建标签。标签的创建由配套工具repokit负责。当仓库缺少工具所需的标签时,立即停止操作并告知用户如何添加(运行,或提供具体的命令),而非自行创建或静默跳过。
repokitgh label create标准标签映射中,同一时间仅激活一个状态标签,按照工作流从左到右切换,三个分支状态可随时适用。该表格是与repokit的共享约定,维护者需确保两个工具的标签名称、颜色和含义保持一致:
| 标签 | 颜色 | 含义 | 通常设置者 |
|---|---|---|---|
| | 已提交,尚未评估或拆分 | create(临时创建)、triage |
| | 内容不够明确,无法开展工作;仍需人工规划/审核 | issuekit create / afkkit gate |
| | 内容明确且独立,可安全转入专属git工作树 | issuekit create |
| | 存在未满足的前置依赖;issue正文中会标注 | issuekit create / sync |
| | 正在工作树中进行开发 | issuekit start |
| | PR已打开,等待审核或合并 | PR编写工具 / sync |
| | 因缺少信息而停滞,需补充细节后才能继续 | triage |
| | 不会被处理 | triage |
| | 被其他issue替代 | triage |
已关闭的issue无需标签,因为关闭状态本身就是完成的标志。
donereadyblockedreadyblockedBlocked by #Ngh issue list --label readyneeds-planningreadyreadyneeds-planningreadygh issue list --label needs-planningready当所需标签缺失时,通过检查一次,然后报告缺失情况而非自行修改:
gh label list仓库中缺少标签。可通过repokit配置工作流标签,或仅添加该标签:blockedgh label create blocked --color D93F0B --description "has an unmet prerequisite (see 'Blocked by #N' in the body)"
仅在标签存在时才应用标签(使用),与工具中的所有修改操作一样,先预览并获得用户批准。
gh issue edit <n> --add-label <label>Priority labels (every mode)
优先级标签(所有模式通用)
The second label namespace, and the one that decides what gets picked up next. Like the lifecycle set, issuekit uses these labels and never creates them: repokit provisions them, and a missing one is reported, not worked around.
| label | color | means | typically set by |
|---|---|---|---|
| | drop everything; preempts work already in progress | issuekit create / triage |
| | do this before other workable issues | issuekit create / triage |
| | normal priority, the default once assessed | issuekit create / triage |
| | worth doing eventually; never preempts anything | issuekit create / triage |
This table is the other half of the shared contract with repokit; keep names, colors, and meanings aligned across both skills.
Lifecycle and priority are orthogonal, so one label from each, and neither implies the other. Lifecycle answers can this be worked?; priority answers should this be worked next? An issue is and , or and , and both are coherent: a issue that's workable right now is still workable, and a one that's blocked is exactly why its blocker matters. Never infer one from the other, because promoting an issue to because it's is how ungrilled work reaches an unattended worker, and the guard exists precisely to stop that.
readyhighblockedcriticallowcriticalreadycriticalreadyNo priority label means unassessed, not . The absence is a real state, and it's the one hunts for. Don't silently default an issue to the middle: an unranked issue that everyone assumes is normal-priority is indistinguishable from one somebody actually thought about, and the whole value of the scale is that distinction. Priority is expected on every open issue except the side-exits (, ), which are going nowhere and need no rank.
mediumtriagewontfixduplicateExactly one priority label at a time, and you have to enforce it, because GitHub won't. Labels are a flat namespace with no mutual exclusion, so nothing stops an issue carrying and at once, and an issue with two priorities sorts unpredictably everywhere downstream. Every write is therefore a replace, not an add: read the issue's current labels, and remove whichever sibling is actually there in the same call that adds the new one.
criticallowsh
gh issue view 42 --json labels -q '[.labels[].name]' # → ["ready","medium"]
gh issue edit 42 --add-label high --remove-label mediumCompute the removal from what the issue actually carries rather than blind-removing all three siblings, because it keeps the preview honest ( reads differently from ) and doesn't depend on how your version handles removing a label that was never there.
medium → highset highgh这是第二个标签命名空间,用于决定任务的处理顺序。与生命周期标签集合一样,issuekit仅使用这些标签,绝不创建标签:repokit负责创建标签,缺失标签时需报告而非绕过。
| 标签 | 颜色 | 含义 | 通常设置者 |
|---|---|---|---|
| | 立即处理;优先于正在进行的工作 | issuekit create / triage |
| | 优先于其他可处理的issue | issuekit create / triage |
| | 正常优先级,评估后的默认值 | issuekit create / triage |
| | 值得处理,但无需优先执行 | issuekit create / triage |
该表格是与repokit的共享约定的另一部分;需确保两个工具的标签名称、颜色和含义保持一致。
生命周期与优先级是正交的,因此每个issue需各选一个标签,且二者互不影响。生命周期回答“该issue是否可处理?”;优先级回答“该issue是否应该优先处理?”。一个issue可以是且,也可以是且,这两种情况都是合理的:优先级但可立即处理的issue仍然是可处理的,但被阻塞的issue恰恰说明了其依赖项的重要性。绝不要从一个标签推断另一个标签,因为仅因优先级为就将issue标记为会导致未审核的工作进入无人值守的处理流程,而标签校验正是为了阻止这种情况。
readyhighblockedcriticallowcriticalcriticalreadyready无优先级标签表示未评估,而非。缺失优先级标签是一种真实状态,也是模式需要排查的情况。不要静默将issue默认设为中等优先级:未排序的issue与经过人工评估的正常优先级issue无法区分,而优先级体系的价值正在于这种区分。除分支状态(、)外,所有打开的issue都应设置优先级,因为这些分支状态的issue不会被处理,无需排序。
mediumtriagewontfixduplicate同一时间仅能设置一个优先级标签,且需强制执行,因为GitHub不会自动约束。标签是扁平命名空间,不支持互斥,因此一个issue可能同时携带和标签,导致其在下游排序时出现不可预测的结果。因此每次修改优先级都是替换操作,而非添加:读取issue当前的标签,在添加新标签的同时移除同命名空间下的旧标签。
criticallowsh
gh issue view 42 --json labels -q '[.labels[].name]' # → ["ready","medium"]
gh issue edit 42 --add-label high --remove-label medium根据issue实际携带的标签计算需要移除的标签,而非盲目移除所有其他三个优先级标签,这样可以让预览内容更准确(与的表述不同),且无需依赖gh版本处理移除不存在的标签时的行为。
medium → high设置为highMode: create
create模式:create
(创建)
createTurn work into issues. Two inputs: a plan file (the main path) or a plain description (start fresh).
将任务转换为issue。支持两种输入:规划文件(主要方式)或普通描述(从零开始)。
1. Find the input
1. 确定输入来源
- Plan path: a . Resolve it by precedence: an explicit path in the prompt → the newest canonical plan under
plan-<slug>-YYYY-MM-DD.md(creation date is the filename suffix) → ask which plan.docs/plans/ - Ad-hoc path: a plain description with no plan. This is the "start fresh, just file it" case → one well-formed issue.
- 规划文件路径:格式为。按优先级解析:提示中明确指定的路径 →
plan-<slug>-YYYY-MM-DD.md下最新的标准规划文件(文件名后缀为创建日期) → 询问用户选择哪个规划文件。docs/plans/ - 临时输入:无规划文件的普通描述。属于“从零开始,直接提交”的场景 → 创建一个结构规范的issue。
2. Decompose a plan into a proposed breakdown
2. 将规划分解为建议的issue结构
Read the plan's structure (phases, milestones, tasks) and decide the shape:
- a parent epic + N child issues when the plan has distinct sub-tasks worth tracking separately, or
- a flat list (or single issue) when it doesn't.
Four principles govern the breakdown, applied before you present anything:
- Fewest issues by default. Actively look for scopes where several related tasks can collapse into one issue with a checklist instead of separate issues. Merge aggressively; only split into its own issue/sub-issue when a task is genuinely independent, meaning a different lifecycle, owner, or PR. Default to the smallest number of issues and sub-issues that still tracks the work honestly. The user can always ask to split one further; starting consolidated and splitting on request beats starting fragmented.
- Vertical slices. Size each issue/sub-issue so it completes one testable feature end to end whenever possible, meaning a slice a person could verify on its own, rather than a horizontal layer (e.g. "all the DB models", "all the endpoints") that isn't demonstrable until other issues land. Prefer "user can log in with SSO" over separate "add OIDC table" / "add OIDC route" / "add OIDC UI" issues; fold those layers into the one vertical slice as checklist items. Size it, too, so one slice fits in a single fresh agent context / worktree session: if a slice couldn't plausibly be finished in one sitting, it's a sign to split it.
- Independent by default. Size and sequence issues so each can be picked up in its own git worktree and worked in parallel, with no issue waiting on another. When two candidate slices share state (a migration one creates and another consumes, an API contract one produces), first try to design the dependency away: fold them into one issue, or resequence so the shared piece ships inside the prerequisite. Only when a real ordering constraint survives do you record it: the dependent gets and a
blockedline, everything else getsBlocked by #N. This is what makes the tracker safe to fan out across worktrees.ready - Prefactor first. Before slicing the feature, look for a simplifying refactor that makes the real change trivial: "make the change easy, then make the easy change." File that refactor as its own issue (behavior-preserving →
ready) that the feature slices then build on. A clean prefactor often removes a dependency that would otherwise force arefactor(scope):chain, so it earns its keep even as an extra issue.blocked
Wide mechanical refactors. When a change has broad blast radius and genuinely can't be one vertical slice, such as renaming a shared column or retyping a symbol used everywhere, don't file it as one giant issue. Sequence it expand → migrate → contract:
- expand. Add the new form alongside the old; nothing breaks yet. .
ready - migrate. Update call sites in batches by area, each batch its own issue by the expand issue (
blocked). The batches are independent of each other, so fan them out in parallel.Blocked by #<expand> - contract. Delete the old form once nothing uses it, by all the migrate batches.
blocked
This turns one un-sliceable change into a fan of mostly-parallel issues with honest edges, and reuses the existing / machinery, with no new labels. If the batches can't each stay green on their own, add one final integrate-and-verify issue blocked by them all.
Blocked by #NreadyblockedMilestones are opt-in. Do not create GitHub milestones by default; map a plan's phases onto issues and checklists instead. Only when the user explicitly asks for milestones (or points at a repo that already uses them) should you create one (, then ) and attach issues to it. Absent that ask, never introduce a milestone the user would then have to maintain.
gh api --method POST repos/{owner}/{repo}/milestones -f title="<title>"gh issue create --milestone <title>Present the proposal as a preview table and stop for approval. Do not create anything yet:
| # | Type | Title | Parent | Priority | Depends on | Checklist |
|---|---|---|---|---|---|---|
| 1 | epic | | none | high | none | none |
| 2 | child | | #1 | high | none | provider · session · token refresh · UI |
| 3 | child | | #1 | medium | #2 | link existing · unlink · conflict handling |
Titles follow the title convention: , lowercase, the epic and its children sharing the scope. Each child is a vertical slice with its layers folded into a checklist, not one issue per layer. The Depends on column is where independence is decided out loud: an empty cell means the issue is , so pick it up in its own worktree now, while a means it's by that issue (row 3 waits on row 2). Keep the column as empty as honesty allows; a mostly-empty column is a tracker the user can fan out in parallel. Let the user add, drop, retitle, reparent, reprioritize, resequence to break a dependency, or split any row before you proceed, and offer splitting explicitly when a slice is large. This guard is the point, so never spray a repo with auto-generated issues.
type(scope): summaryauthready#NblockedPropose a priority per row, and expect to be overruled. You can read relative importance off a plan, meaning what it calls out as the core of the feature versus the polish, what it defers, and what it flags as a risk, and that's a real signal worth putting in the column. What you cannot read is why the work is being done at all, which is the thing priority actually encodes. So propose from the plan, mark anything the plan doesn't rank as , and treat the column as the one most likely to be corrected. This is exactly the right moment for that correction: setting priority here costs the user one glance at a table they're already reviewing, where doing it later means a pass back over issues that have scattered across the tracker.
mediumDon't hand out from a plan. It means preempt work already in progress, which is a claim about right now and not about the plan, and a document written last week cannot know what's in flight today. Propose for the most important row and let the user escalate it if they mean it.
criticalhighFor an ad-hoc description, skip the table: draft one issue (title + body) and confirm it before creating.
读取规划的结构(阶段、里程碑、任务)并确定issue形态:
- 当规划包含多个可独立追踪的子任务时,分解为父epic + N个子issue;
- 否则分解为扁平列表(或单个issue)。
分解需遵循以下四个原则,且需在呈现给用户前应用:
- 默认最少issue数量:主动寻找可将多个相关任务合并为一个包含checklist的issue的场景,而非拆分为多个独立issue。尽可能合并;仅当任务确实独立(具有不同的生命周期、负责人或PR)时才拆分为独立issue/子issue。默认使用能如实追踪任务的最少issue和子issue数量。用户可随时要求进一步拆分;从合并状态开始,按需拆分,比一开始就碎片化处理更优。
- 垂直切片:调整每个issue/子issue的大小,使其尽可能完成一个可独立测试的端到端功能,即用户可单独验证的切片,而非水平层(例如“所有数据库模型”“所有接口”),这类水平层需等待其他issue完成后才能展示效果。优先选择“用户可通过SSO登录”而非拆分为“添加OIDC表”/“添加OIDC路由”/“添加OIDC UI”等独立issue;将这些层级合并为一个垂直切片的checklist项。同时调整大小,确保一个切片可在单个Agent上下文/工作树会话中完成:如果一个切片无法在一次会话中完成,则说明需要拆分。
- 默认独立可并行:调整issue的大小和顺序,确保每个issue都能在独立的git工作树中处理,且可并行进行,无需等待其他issue。当两个候选切片共享状态(例如一个切片创建的迁移被另一个切片使用,一个切片生成的API契约被另一个切片调用)时,首先尝试消除依赖:将它们合并为一个issue,或调整顺序使共享部分包含在前置依赖中。仅当确实存在顺序约束时才记录依赖:依赖的issue标记为并添加
blocked行,其余issue标记为Blocked by #N。这是确保追踪器可安全并行处理的关键。ready - 先重构再开发:在拆分功能前,寻找可简化后续修改的重构操作:“让修改变得简单,再进行简单的修改。” 将该重构操作创建为独立的issue(不改变功能 →
ready),功能切片基于该重构后的代码开发。合理的重构通常会消除原本会导致阻塞链的依赖,因此即使多创建一个issue也是值得的。refactor(scope):
大范围机械重构:当修改影响范围广且无法拆分为单个垂直切片时,例如重命名共享列或修改全局使用的符号,不要创建一个巨型issue。应按照扩展 → 迁移 → 收缩的顺序拆分:
- 扩展:在保留旧版本的同时添加新版本;此时不会破坏现有功能。标记为。
ready - 迁移:按区域分批更新调用方,每批作为独立issue,标记为并依赖扩展issue(
blocked)。各批次之间相互独立,可并行处理。Blocked by #<expand> - 收缩:当所有调用方都已迁移后,删除旧版本;标记为并依赖所有迁移批次。
blocked
这样可将一个无法拆分的修改转换为一组大部分可并行处理的issue,并通过/机制管理依赖,无需新增标签。如果各批次无法单独保持正常运行,则添加一个最终的集成验证issue,依赖所有迁移批次。
readyblocked里程碑为可选功能。默认不创建GitHub里程碑;将规划的阶段映射为issue和checklist即可。仅当用户明确要求使用里程碑(或仓库已在使用里程碑)时,才创建里程碑(,然后使用关联issue)。若无明确要求,绝不创建用户后续需要维护的里程碑。
gh api --method POST repos/{owner}/{repo}/milestones -f title="<title>"gh issue create --milestone <title>将拆分建议以预览表格形式呈现给用户,并等待批准。此时不要创建任何内容:
| # | 类型 | 标题 | 父issue | 优先级 | 依赖项 | Checklist |
|---|---|---|---|---|---|---|
| 1 | epic | | 无 | high | 无 | 无 |
| 2 | child | | #1 | high | 无 | provider · session · token refresh · UI |
| 3 | child | | #1 | medium | #2 | link existing · unlink · conflict handling |
标题遵循标题规范:,全小写,epic及其子issue共享scope。每个子issue都是一个垂直切片,其层级被折叠为checklist项,而非每个层级对应一个issue。依赖项列用于明确独立性:空单元格表示issue为,可立即转入工作树处理;表示该issue被对应issue阻塞(第3行等待第2行完成)。尽可能保持该列为空;大部分为空的列表示追踪器支持并行处理。允许用户添加、删除、重命名、重新设置父issue、重新排序优先级、调整顺序以打破依赖或拆分任意行,当切片较大时主动提供拆分选项。该校验是关键环节,绝不要自动在仓库中创建大量issue。
type(scope): summaryauthready#N为每一行建议一个优先级,并预期会被用户修改。可从规划中读取相对重要性,例如规划中强调的功能核心与次要功能、延迟处理的内容、标记的风险点,这些都是有价值的信号,可填入该列。但无法读取任务的根本目的,而这正是优先级的核心依据。因此根据规划建议优先级,将规划未提及的项标记为,并将该列视为最可能被修改的部分。这是修改优先级的最佳时机:用户在查看表格时只需 glance 一眼即可调整,而后续修改则需要重新遍历已分散在追踪器中的issue。
medium不要从规划中直接设置优先级。该优先级表示优先于正在进行的工作,这是针对当前状态的判断,而非规划中的内容,上周编写的文档无法知晓当前正在进行的工作。将最重要的行建议为优先级,由用户决定是否升级为。
criticalhighcritical对于临时输入的描述,跳过表格环节:起草一个issue(标题 + 正文)并在创建前确认。
3. Create the issues
3. 创建issue
Guard against duplicates first. create is the workflow's entry point and gets re-invoked, so running it twice on one plan must not file a second set. Before creating, list existing issues and skip (or flag for the user) any whose title already matches:
sh
gh issue list --state all --limit 200 --json number,title,stateOn trackers with more than 200 issues, raise the limit or use so older duplicates are not silently missed.
gh search issues --repo {owner}/{repo} --match title "<candidate title>"Then write each issue with a title in the convention and a body that carries the relevant slice of the plan: context, acceptance criteria, and any decisions. Create parents before children so child bodies can reference them.
type(scope): summaryTwo conventions for the body:
- Write acceptance criteria as checkboxes, giving a concrete, verifiable definition of done for this issue. (Distinct from the sub-issue/parent checklist below, which tracks child issues.)
- [ ] - Don't hard-code file paths, because they go stale as the branch evolves; describe the change by behavior and area instead. The one exception is a decision-rich snippet (a schema, state machine, type, reducer) where the decision is the code, so include it, trimmed to just the substantive part.
sh
gh issue create --title "epic(auth): add sso login" --body-file <bodyfile>Use a temp file for each body (multi-line markdown through is flaky) and clean it up after.
--body首先检查重复项。create是工作流的入口,可能会被重复调用,因此对同一规划执行两次create操作不应创建重复的issue。创建前,列出已存在的issue,跳过(或标记给用户)标题已匹配的issue:
sh
gh issue list --state all --limit 200 --json number,title,state对于issue数量超过200的追踪器,提高限制或使用,避免遗漏旧的重复issue。
gh search issues --repo {owner}/{repo} --match title "<candidate title>"然后按照规范编写每个issue的标题,正文包含规划中对应的部分:上下文、验收标准和已做出的决策。先创建父issue,再创建子issue,以便子issue的正文可引用父issue。
type(scope): summary正文需遵循两个规范:
- 将验收标准写为复选框,为该issue提供具体、可验证的完成定义。(与子issue/父issue的checklist不同,后者用于追踪子issue。)
- [ ] - 不要硬编码文件路径,因为分支演化后路径会失效;应通过行为和区域描述修改内容。唯一例外是包含决策的代码片段(例如 schema、状态机、类型、reducer),此时决策本身就是代码,因此可包含该片段,但仅保留实质性部分。
sh
gh issue create --title "epic(auth): add sso login" --body-file <bodyfile>使用临时文件存储每个正文(通过传递多行markdown不可靠),并在创建后清理临时文件。
--body4. Link parents → children
4. 建立父→子issue关联
Try GitHub's native sub-issues first, then fall back:
sh
undefined优先尝试GitHub的原生子issue功能,失败则回退到其他方式:
sh
undefinedNative (preferred): attach a child to its parent via the sub-issues API.
原生方式(首选):通过子issue API将子issue关联到父issue。
sub_issue_id is the child's DATABASE id (an integer), NOT the GraphQL node id
sub_issue_id是子issue的数据库ID(整数),而非gh issue view --json id
返回的GraphQL节点ID。通过REST端点获取:
gh issue view --json idthat gh issue view --json id
returns. Resolve it from the REST endpoint:
gh issue view --json id—
child_id=$(gh api repos/{owner}/{repo}/issues/{child_number} --jq .id)
child_id=$(gh api repos/{owner}/{repo}/issues/{child_number} --jq .id)
Attach it, using -F (typed integer), not -f (which would send a string and be rejected):
关联子issue,使用-F(传递整数类型),而非-f(会传递字符串并被拒绝):
gh api --method POST repos/{owner}/{repo}/issues/{parent_number}/sub_issues
-F sub_issue_id="$child_id"
-F sub_issue_id="$child_id"
If that call fails, whether because sub-issues are disabled, on older GitHub Enterprise, or through insufficient permissions, **fall back** to a task-list checklist in the parent body and **tell the user which path was used**:
```markdowngh api --method POST repos/{owner}/{repo}/issues/{parent_number}/sub_issues
-F sub_issue_id="$child_id"
-F sub_issue_id="$child_id"
如果该调用失败(例如子issue功能被禁用、GitHub Enterprise版本过旧或权限不足),则**回退**到在父issue正文中添加任务列表checklist,并**告知用户使用的方式**:
```markdownSub-issues
子issue
- #43 wire OIDC provider
- #44 session + token refresh
undefined- #43 对接OIDC提供商
- #44 会话 + token刷新
undefined5. Label lifecycle state and priority, and record dependencies
5. 设置生命周期和优先级标签,并记录依赖
Apply the lifecycle labels so the fresh issues advertise their state. The grill gate decides which vocabulary applies, because is a promise the work can run unattended, earned only when the decisions are already settled:
ready- Grilled source. The input plan file carries a stamp (grillkit writes it when it hardens a plan), or the user explicitly says the work is grilled/ready. The decisions are settled, so the normal pair applies: every independent issue gets
Grilled: YYYY-MM-DD, every dependent one getsreadyplus ablockedline in its body naming the prerequisite.Blocked by #N - Ungrilled source. An ad-hoc description, or a plan with no grill stamp. The decisions aren't settled, so every issue gets , because it still needs a human plan/grill session before anything unattended should touch it. Record any
needs-planningdependency in the body anyway; it takes effect once the issue is grilled intoBlocked by #N. This is what keeps afkkit (and any unattended worker) from picking up work a human hasn't grilled yet.ready
Then apply the priority label the user approved in the preview table, one per issue, in the same call as the lifecycle label, so a fresh issue never exists in a half-labeled state that a concurrent survey could read.
gh issue editPriority is applied regardless of the grill gate. The gate governs the lifecycle namespace only: an ungrilled issue is because nobody has settled its decisions, but "this matters more than that" is a judgment the user just made in the preview and it doesn't need a grill session to be true. Dropping it here would mean the ungrilled backlog, the exact pile that most needs ordering, is the one part of the tracker nothing can rank.
needs-planningConfirm each label exists first (), and if one is missing, stop and point the user at repokit or the line rather than creating it yourself. Check both namespaces in that one call; a repo that predates priority will have the lifecycle nine and none of the four.
gh label listgh label createsh
undefined应用生命周期标签,让新创建的issue展示其状态。审核校验决定使用哪个标签,因为是任务可无人值守处理的承诺,仅当决策已敲定后才能获得该标签:
ready- 已审核的来源:输入的规划文件带有标记(grillkit在固化规划时添加),或用户明确表示任务已审核/就绪。决策已敲定,因此应用常规标签:所有独立issue标记为
Grilled: YYYY-MM-DD,所有依赖issue标记为ready并在正文中添加blocked行说明前置依赖。Blocked by #N - 未审核的来源:临时描述或无审核标记的规划文件。决策未敲定,因此所有issue标记为,因为在无人值守处理前仍需人工规划/审核。仍需在正文中记录
needs-planning依赖;当issue被审核为Blocked by #N后,该依赖生效。这可防止afkkit(或任何无人值守处理工具)接手未经过人工审核的任务。ready
然后应用用户在预览表格中批准的优先级标签,每个issue一个标签,与生命周期标签在同一个调用中设置,确保新创建的issue不会处于半标签状态,避免被并发扫描读取错误信息。
gh issue edit无论是否经过审核,都需设置优先级。审核校验仅影响生命周期标签:未审核的issue标记为是因为决策未敲定,但“这个任务比那个更重要”是用户在预览中做出的判断,无需审核即可生效。如果在此处忽略优先级设置,那么最需要排序的未审核待办事项将成为追踪器中无法排序的部分。
needs-planning先确认每个标签存在(使用),如果标签缺失,则停止操作并引导用户使用repokit或命令添加,而非自行创建。在一次调用中检查两个命名空间的标签;未使用优先级标签的仓库会有9个生命周期标签,但没有4个优先级标签。
gh label listgh label createsh
undefinedgrilled plan → ready / blocked, each with its approved priority
已审核的规划 → ready / blocked,每个issue带有批准的优先级
gh issue edit 43 --add-label ready --add-label high
gh issue edit 44 --add-label blocked --add-label medium # body carries: Blocked by #43
gh issue edit 43 --add-label ready --add-label high
gh issue edit 44 --add-label blocked --add-label medium # 正文包含:Blocked by #43
ungrilled source → needs-planning, still ranked
未审核的来源 → needs-planning,仍设置优先级
gh issue edit 45 --add-label needs-planning --add-label low
Preview the label set alongside the issues and get an OK before applying, as with any other mutation.gh issue edit 45 --add-label needs-planning --add-label low
与其他修改操作一样,先预览标签设置并获得用户批准后再应用。6. Write the issue numbers back into the plan
6. 将issue编号写回规划文件
Once issues exist, annotate the source so it stays the source of truth. Add the ref next to each task it maps to without changing its creation-date suffix:
plan-<slug>-YYYY-MM-DD.mdmarkdown
undefined创建issue后,注释源文件,使其保持为事实来源。在对应的任务旁添加issue引用,不要修改文件名的日期后缀:
plan-<slug>-YYYY-MM-DD.mdmarkdown
undefinedPhase 2: auth (#41)
第二阶段:认证(#41)
- OIDC provider (#43)
- session + token refresh (#44)
Use `Edit` for this. For an ad-hoc issue with no plan file, skip this step.- OIDC提供商(#43)
- 会话 + token刷新(#44)
使用`Edit`操作完成该步骤。对于无规划文件的临时issue,跳过该步骤。7. Hand off
7. 交接
Write every hand-off in this skill in the procedural register: one instruction per sentence, active voice, present tense, no metaphor.
What changed. Give a table of what you created: number, title, parent, URL, lifecycle label, and priority. Note whether links used native sub-issues or the task-list fallback, and that the plan was annotated.
Where it landed. Call out the set (issues the user can start in parallel worktrees right now) versus the set, naming what each blocked issue waits on. Order the set by priority, since that set exists to be picked from.
readyblockedreadyNext. Route on which set came back non-empty, naming a sibling kit only when it's installed and otherwise describing the action plainly:
- issues exist → pick one up with
ready, which gets it a worktree and flips itstart <n>. Crown the highest-priority one rather than listing all of them, breaking a tie on whichever frees the most other work.in-progress - everything is (an ungrilled source) → the next move is a human grill session, meaning grillkit on the plan, then re-run
needs-planning, or relabel by hand once the decisions are settled. Nothing here is workable unattended yet, so say that plainly rather than offeringcreate.start - everything is → surface the root prerequisite; that's the only thing anyone can act on.
blocked
工具中所有交接内容均使用过程式表述:每句一个指令,主动语态,现在时态,无隐喻。
变更内容:以表格形式列出创建的issue:编号、标题、父issue、URL、生命周期标签和优先级。说明关联使用的是原生子issue还是任务列表回退方式,以及规划文件已被注释。
当前状态:指出**集合**(用户可立即在并行工作树中启动的issue)与**集合**,说明每个阻塞issue等待的依赖项。按优先级排序集合,因为该集合是用户选择处理任务的依据。
readyblockedready下一步操作:根据非空集合进行引导,仅当配套工具已安装时才提及工具名称,否则直接描述操作:
- 存在issue → 使用
ready启动其中一个,为其创建工作树并切换为start <n>状态。优先选择最高优先级的issue,若优先级相同则选择能解锁最多其他任务的issue。in-progress - 所有issue均为(未审核的来源) → 下一步是人工审核会话,即对规划使用grillkit,然后重新运行
needs-planning,或在决策敲定后手动修改标签。此时没有可无人值守处理的任务,因此需明确说明,不要提供create选项。start - 所有issue均为→ 指出最根本的前置依赖;这是唯一可操作的内容。
blocked
Mode: start
start模式:start
(启动)
startPick an issue up: guard that it's actually workable, get it a worktree, and move it to . This is the moment the tracker and the filesystem meet, and it is deliberately thin: the tracker half is issuekit's, the worktree half is gitkit's, and there is nothing in between.
in-progress接手issue:校验其是否可处理、为其创建工作树、并将状态切换为。这是追踪器与文件系统交互的环节,设计上尽可能简洁:追踪器部分由issuekit负责,工作树部分由gitkit负责,二者互不干涉。
in-progress1. Guard: refuse anything not ready
ready1. 校验:拒绝非ready
的issue
readyNever start an issue that isn't labeled .
readysh
gh issue view <n> --json labels,title,stateThis one guard carries more weight than its size suggests, and it is the reason lives here rather than in a worktree skill. An issue only reaches two ways: a human grilled its decisions settled, or issuekit promoted it when its prerequisite landed. So refusing everything else enforces both the dependency graph and the human-grill gate for free: no unattended worker can get ahead of the tracker, and none can get ahead of human judgment.
startreadysyncblocked → readyThat last part is load-bearing for an orchestrator that calls itself with nobody watching (afkkit does exactly this, as the first step of every run). The gate does not depend on who types the command: it's the label that carries the human's judgment, earned upstream at the grill, and nothing that calls can award it. So refuse on the label alone, and never soften the guard because the caller sounds confident, names a plan, or says it's fine.
startreadystartRefuse with the reason, not a bare error:
- → the decisions aren't settled; it needs a human grill session first.
needs-planning - → name the
blockedprerequisite and its state.Blocked by #N - → it's already started; go to the adopt path below rather than treating this as a failure.
in-progress - closed, or no lifecycle label → say which, and offer to classify it.
triage
绝不启动未标记为的issue。
readysh
gh issue view <n> --json labels,title,state该校验的重要性远超其代码量,这也是模式属于issuekit而非工作树工具的原因。一个issue只有两种方式获得标签:人工审核确认决策已敲定,或issuekit的模式在其前置依赖完成后将其从升级为。因此拒绝所有非的issue可同时强制执行依赖图和人工审核校验:无人值守处理工具无法超前于追踪器,也无法超前于人工判断。
startreadysyncblockedreadyready这一点对于无人值守的编排器(例如afkkit,它会在每次运行的第一步自动调用)至关重要。校验不依赖调用者:标签承载的是人工判断,在审核环节已获得,任何调用的工具都无法授予该标签。因此仅根据标签拒绝,绝不要因调用者自信、提及规划或表示没问题而放宽校验。
startreadystart拒绝时需说明原因,而非仅返回错误:
- → 决策未敲定;需先进行人工审核会话。
needs-planning - → 说明
blocked的前置依赖及其状态。Blocked by #N - → 该issue已启动;请使用下方的复用路径,不要视为失败。
in-progress - 已关闭或无生命周期标签 → 说明具体情况,并提供模式进行分类。
triage
2. Derive the branch name
2. 生成分支名称
gitkit owns branch naming, so hand it the issue number and title and use what comes back. For an issue titled in the convention, that yields : the prefix stripped, the summary kebab-cased and capped. Don't re-derive the shape here; a second copy of the slug rules drifts from the one gitkit uses to find the worktree later, and then lookup silently stops matching.
type(scope): summaryissue-<n>-<slug>分支命名由gitkit负责,因此将issue编号和标题传递给gitkit,使用其返回的分支名称。对于符合标题规范的issue,分支名称格式为:去掉前缀,将摘要转换为短横线分隔的小写形式并截断。不要在此处重新生成分支名称;分支规则的重复实现会与gitkit后续查找工作树时使用的规则产生偏差,导致查找失败。
issue-<n>-<slug>3. Get the worktree from gitkit, create or adopt
3. 通过gitkit获取工作树,创建或复用
Call gitkit for the branch. It looks the branch up first and adopts an existing worktree if there is one, creating a fresh one off the resolved base ref only when there is none. That is what makes safe to re-run: the re-run path is real (an issue escalated back to , grilled, and picked up again), and it must never recreate, never error, and never disturb work already sitting in the worktree.
startneeds-planningissuekit does not choose the path, the base ref, or the git commands. If gitkit isn't installed, say so and stop rather than improvising a worktree convention, because a worktree in the wrong place is worse than none, since everything downstream then looks in the right place and finds nothing.
调用gitkit获取分支。gitkit会先查找分支,如果存在现有工作树则复用,仅当不存在时才基于解析后的基础引用创建新的工作树。这使得模式可安全重复调用:重复调用的场景真实存在(例如issue被升级为,经过审核后再次接手),且重复调用绝不应重新创建工作树、返回错误或干扰已存在于工作树中的内容。
startneeds-planningissuekit不选择路径、基础引用或git命令。如果未安装gitkit,则告知用户并停止操作,不要自行制定工作树规则,因为错误位置的工作树比没有工作树更糟,后续所有操作都会在正确位置查找而一无所获。
4. Flip the label ready → in-progress
ready → in-progress4. 切换标签ready → in-progress
ready → in-progresssh
gh issue edit <n> --remove-label ready --add-label in-progressRun it without asking. This is the skill's single exemption from the preview rule, it applies to every caller, and it applies to this flip and nothing else. Report the flip in the hand-off rather than proposing it first. If the issue was already (the adopt path), leave the label alone and say so. If either label is missing from the repo, report the gap and point at repokit, because the exemption skips the prompt, never the provisioning check.
in-progresssh
gh issue edit <n> --remove-label ready --add-label in-progress无需询问直接执行。这是工具中唯一无需预览的例外,对所有调用者生效,且仅适用于该标签切换。在交接环节报告该切换,而非提前提议。如果issue已处于状态(复用路径),则保持标签不变并说明情况。如果任一标签缺失,则报告缺失情况并引导用户使用repokit,因为例外仅跳过提示,而非跳过标签校验。
in-progress5. Hand off
5. 交接
What changed. Report the label move (, or that it was left alone on the adopt path).
ready → in-progressWhere it landed. Give the branch and the worktree path, and whether it was created fresh or adopted.
Next. The ground is prepared and nothing has been built, so the next move is always switch into that worktree and start there. Give the and name the builder: implementkit against this issue when it's installed, otherwise plain "implement the issue in that worktree". For an unattended run, afkkit takes it from here to an open PR, and since afkkit calls itself, mention it as from anywhere rather than as something to run from inside the worktree; it adopts the worktree this run just prepared.
cdstartafkkit <n>Stop there. prepares the ground and nothing else. It does not implement, does not launch an agent, and does not commit; naming the next step is routing, not doing it.
start变更内容:报告标签切换(,或复用路径下保持标签不变)。
ready → in-progress当前状态:提供分支名称和工作树路径,说明是新创建还是复用的工作树。
下一步操作:环境已准备就绪,尚未开始开发,因此下一步始终是切换到该工作树并开始开发。提供命令,并指定开发工具:已安装implementkit时使用其处理该issue,否则直接说明“在该工作树中实现issue内容”。对于无人值守运行,afkkit会从该环节继续处理直到打开PR,由于afkkit会自行调用,因此可在任何位置提及,而非仅在工作树中运行;它会复用本次运行准备的工作树。
cdstartafkkit <n>到此为止。模式仅负责准备环境,不负责实现、启动Agent或提交代码;提及下一步操作是引导,而非执行操作。
startMode: close
close模式:close
(关闭)
closeThe other bookend to : the issue's PR has merged, so close it out and reclaim its workspace. Every step here is destructive or outward-facing, so unlike this mode previews and waits for an OK before it mutates anything.
startstart与模式形成首尾呼应:issue对应的PR已合并,因此关闭issue并回收其工作空间。本模式的每一步都是破坏性或对外操作,因此与不同,本模式需先预览并等待用户批准后再执行修改。
startstart1. Confirm the PR actually merged, a hard precondition
1. 确认PR已合并,这是硬性前置条件
sh
gh pr list --search "<n>" --state merged --json number,title,url,closingIssuesReferences
gh pr view <pr> --json state,mergedAtA merged PR is required, not assumed. If none is found, whether no PR at all or one that's still open, does nothing: no close, no label change, no worktree removal. Report exactly what's blocking (, ) and stop.
closePR #X still openno PR found for #NThis precondition is the whole reason is safe to run on a name you half-remember. Its two irreversible acts, closing the issue and deleting a worktree, are both gated behind evidence that the work actually landed. A forced teardown of unlanded work stays a deliberate thing the user does themselves, through gitkit directly.
closesh
gh pr list --search "<n>" --state merged --json number,title,url,closingIssuesReferences
gh pr view <pr> --json state,mergedAt必须有已合并的PR,不能假设。如果未找到已合并的PR(例如根本没有PR或PR仍处于打开状态),模式不执行任何操作:不关闭issue、不修改标签、不删除工作树。准确报告阻塞原因(、)并停止操作。
closePR #X仍处于打开状态未找到与#N对应的PR该前置条件是模式可安全运行的核心原因,即使用户仅记得部分信息也可放心使用。其两个不可逆操作(关闭issue和删除工作树)均以工作已完成为前提。未完成工作的强制清理需由用户通过gitkit自行执行。
close2. Preview, then confirm
2. 预览并确认
Show the full consequence in one line and wait:
PR #10 () merged → close #42, tick parent #41's checklist, unblock #44, remove the worktree forfeat(auth): add sso login.issue-42-add-sso-login
Name every effect, including the ones that feel routine. Unblocking a dependent changes what someone else picks up next; removing a worktree deletes a directory they may have a terminal sitting in.
以一行文字展示所有后果并等待用户批准:
PR #10 ()已合并 → 关闭#42,勾选父issue #41的checklist,解锁#44,删除feat(auth): add sso login对应的工作树。issue-42-add-sso-login
列出所有影响,包括常规操作。解锁依赖项会改变其他人接下来的任务选择;删除工作树会删除用户可能正在使用的终端所在的目录。
3. Reconcile the tracker
3. 协调追踪器
Close the issue, tick the parent epic's checklist, and flip any dependents . This is 's job and reuses it rather than restating it, so apply Reconcile, Checklist, and Labels to this one issue:
blocked → readysyncclosesh
gh issue close <n> --comment "Closed by #<pr> (merged)."
gh issue edit <n> --remove-label in-review --remove-label in-progresstick "- [ ] #<n>" → "- [x] #<n>" in a task-list parent's body
将父issue正文中的"- [ ] #<n>"修改为"- [x] #<n>"
for each dependent whose body says "Blocked by #<n>":
对于每个正文中包含"Blocked by #<n>"的依赖项:
gh issue edit <dep> --remove-label blocked --add-label ready
Closing strips the active status label in the same action, because a closed issue must never carry a stale `in-review`. Native sub-issues tick themselves; only the task-list fallback needs the body edit.gh issue edit <dep> --remove-label blocked --add-label ready
关闭issue时需同时移除活跃状态标签,因为已关闭的issue不应携带过期的`in-review`标签。原生子issue会自动勾选checklist;仅任务列表回退方式需要修改正文。4. Tear the worktree down through gitkit, keyed on the branch
4. 通过gitkit清理工作树,基于分支查找
Hand this to gitkit, which looks the worktree up by its branch () through . Lookup is by branch, never by guessing at a path, which is what lets it find a worktree that predates the current path convention, or one that was moved.
issue-<n>-<slug>git worktree list --porcelaingitkit's own teardown rules apply and issuekit does not override them:
- A dirty worktree stops the removal and shows what would be lost. A merged PR does not guarantee an empty worktree: scratch files, a stashed experiment, or an un-pushed follow-up commit all live there, and none of them are in the PR.
- Already gone → "already gone", not an error. is idempotent in the same spirit as
close's adopt-and-stop; re-running it after a partial run is normal.start - The branch is deleted only if it's merged, with rather than
-d, so git itself refuses to drop unmerged work.-D
If no worktree matches the branch, say so and carry on, because the tracker half of still succeeded.
close将该操作交给gitkit,它会通过基于分支()查找工作树。基于分支查找,而非猜测路径,这样可找到遵循旧路径规则或被移动过的工作树。
git worktree list --porcelainissue-<n>-<slug>gitkit自身的清理规则适用,issuekit不覆盖:
- 脏工作树会阻止删除,并显示会丢失的内容。PR合并不代表工作树为空:临时文件、暂存的实验代码或未推送的后续提交都可能存在于工作树中,且未包含在PR中。
- 工作树已不存在 → 提示“已不存在”,而非返回错误。模式与
close模式的复用逻辑一样,具有幂等性;部分执行后重新运行是正常场景。start - 仅当分支已合并时才删除分支,使用而非
-d,因此git会拒绝删除未合并的工作。-D
如果未找到与分支匹配的工作树,则说明情况并继续执行,因为模式的追踪器部分已成功完成。
close5. Hand off
5. 交接
What changed. Report the issue closed and by which PR, the parent ticked, and each dependent unblocked ().
blocked → readyWhere it landed. Say whether the worktree was removed, left dirty, or already gone. If it survived, name the path and why, so it doesn't quietly linger.
Next. Closing an issue is the moment a slot opens up, so point at what fills it, naming a kit only when it's installed:
- this close unblocked something → that dependent is the strongest candidate; name it and offer .
start <n> - nothing was unblocked, but issues exist → offer
readyon the most-recently-updated one.start - nothing is → the workable queue is empty, so the move is back up the funnel: statuskit to re-orient, or
readyif the tracker looks like it's hiding work.triage - the worktree survived dirty → that outranks everything above. Say it first; unlanded work in a stale worktree is what gets lost.
变更内容:报告issue已关闭及对应的PR、父issue的checklist已勾选、每个依赖项已解锁()。
blocked → ready当前状态:说明工作树是否被删除、因脏数据保留或已不存在。如果工作树保留,说明路径和原因,避免其被遗忘。
下一步操作:关闭issue会释放一个处理槽位,因此指出可接手的任务,仅当配套工具已安装时才提及工具名称:
- 本次关闭解锁了任务 → 该依赖项是最佳候选;提及该issue并提供选项。
start <n> - 未解锁任务,但存在issue → 提供
ready选项,选择最近更新的issue。start - 无issue → 可处理的队列已空,因此需回到上游环节:使用statuskit重新梳理,或使用
ready模式排查追踪器中是否隐藏了任务。triage - 工作树因脏数据保留 → 该情况优先级最高。首先说明该情况;未完成的工作存在于过期工作树中容易丢失。
Mode: sync
sync模式:sync
(同步)
syncReconcile and repair the PR↔issue relationship. Sync deliberately does not write the forward link onto a fresh PR, because that belongs to the PR-authoring step (a prkit-style skill) at open time. Sync only earns its place where the automatic chain broke:
Closes #N| Who | Owns |
|---|---|
| PR-authoring skill | write |
| issuekit sync | reconcile drift after merge, repair a missing link on an existing PR, tick parent checklists, advance lifecycle labels and unblock dependents |
协调并修复PR与issue的关联。Sync模式绝不会在新PR中添加正向链接,因为这属于PR编写环节(prkit类工具)在打开PR时的工作。Sync模式仅处理自动关联失效的场景:
Closes #N| 负责方 | 职责 |
|---|---|
| PR编写工具 | 在新PR打开时添加 |
| issuekit sync | 合并后协调偏差、修复现有PR缺失的关联链接、勾选父issue的checklist、更新生命周期标签并解锁依赖项 |
1. Reconcile a merged PR whose issue never closed
1. 合并后PR对应的issue未关闭的协调
Find PRs merged recently whose linked issue is still open because the keyword was missing:
Closes #sh
gh pr list --state merged --limit 20 --json number,title,body,closingIssuesReferences
gh issue list --state open --json number,titleFor each merged PR that should have closed an issue (evident from the branch, title, plan, or the user telling you), preview it and confirm before closing:
PR #10 () merged, but issue #42 is still open → close #42 with a comment linking the PR?feat(auth): add sso login
On approval:
sh
gh issue close 42 --comment "Closed by #10 (merged)."Closing is a lifecycle transition too, so strip any active status label (, , …) in the same action and a closed issue never carries a stale status (see Labels: advance lifecycle state). Never auto-close, and always show the pairing and wait for the OK. If which issue a PR should have closed is ambiguous, ask rather than guess, because closing the wrong issue is worse than leaving one open.
in-reviewin-progress查找最近合并的PR,这些PR因缺失关键字导致对应的issue仍处于打开状态:
Closes #sh
gh pr list --state merged --limit 20 --json number,title,body,closingIssuesReferences
gh issue list --state open --json number,title对于每个应该关闭issue的已合并PR(可从分支、标题、规划或用户告知中判断),先预览并确认后再关闭:
PR #10 ()已合并,但issue #42仍处于打开状态 → 是否关闭#42并添加关联PR的注释?feat(auth): add sso login
获得批准后执行:
sh
gh issue close 42 --comment "Closed by #10 (merged)."关闭issue也是生命周期转换,因此需在同一操作中移除所有活跃状态标签(、等),确保已关闭的issue不会携带过期状态标签(详见标签:更新生命周期状态)。绝不自动关闭,始终展示配对关系并等待批准。如果PR对应的issue不明确,请询问用户而非猜测,因为关闭错误的issue比遗留打开的issue更严重。
in-reviewin-progress2. Repair a missing link on an existing open PR
2. 修复现有打开PR缺失的关联链接
If an open PR should reference an issue but doesn't, add to its body (editing the existing PR, not opening a new one):
Closes #Nsh
gh pr edit <pr> --body-file <updated-body>如果打开状态的PR应关联issue但未关联,则在其正文中添加(编辑现有PR,而非打开新PR):
Closes #Nsh
gh pr edit <pr> --body-file <updated-body>3. Checklist: tick the parent when a child closes
3. Checklist:子issue关闭时勾选父issue的checklist
The task-list fallback () does not auto-tick when the child closes; native sub-issues do. When a child issue is closed, update the parent body to check its box:
- [ ] #childsh
gh issue view <parent> --json body -q .body # read
gh issue edit <parent> --body-file <updated> # write back with - [x] #child任务列表回退方式()不会在子issue关闭时自动勾选;原生子issue会自动勾选。当子issue关闭时,更新父issue的正文以勾选对应的复选框:
- [ ] #childsh
gh issue view <parent> --json body -q .body # 读取正文
gh issue edit <parent> --body-file <updated> # 写回修改后的正文,将- [ ] #child改为- [x] #child4. Labels: advance lifecycle state, unblock what's freed
4. 标签:更新生命周期状态,解锁依赖项
Move issues through the lifecycle labels as PRs advance: an issue whose PR just opened → ; and, the dependency payoff, when an issue that was a blocker closes, find the issues whose body says and swap them → , optionally commenting that the prerequisite landed:
in-reviewBlocked by #<it>blockedreadysh
gh issue edit 44 --remove-label blocked --add-label ready
gh issue comment 44 --body "Unblocked: #43 (the prerequisite) merged."
gh issue edit 42 --remove-label in-review # closing → strip the active status label; the closed state is the signalAs everywhere in sync, preview each move and wait for the OK, and never auto-relabel. If a label the map needs isn't provisioned, stop and point the user at repokit or the line, because issuekit uses labels and doesn't create them. If the repo predates this map and runs its own status scheme, follow that instead and say you did.
gh label create随着PR推进,更新issue的生命周期标签:PR刚打开的issue → ;当作为阻塞依赖的issue关闭时,查找正文中包含的issue,将其从切换为,可选添加注释说明前置依赖已完成:
in-reviewBlocked by #<it>blockedreadysh
gh issue edit 44 --remove-label blocked --add-label ready
gh issue comment 44 --body "已解锁:#43(前置依赖)已合并。"
gh issue edit 42 --remove-label in-review # 关闭issue → 移除活跃状态标签;关闭状态本身就是信号与sync模式中的所有操作一样,先预览每一步操作并等待用户批准,绝不自动修改标签。如果映射所需的标签未配置,则停止操作并引导用户使用repokit或命令添加,因为issuekit仅使用标签,不创建标签。如果仓库早于该映射并使用自己的状态体系,则遵循仓库自身的规范并说明情况。
gh label create5. Hand off
5. 交接
What changed. Report issues closed, PR bodies repaired, checklists ticked, and issues advanced or unblocked ( → ), each an action the user approved. Say plainly if nothing needed repairing; a clean sweep is a real result.
blockedreadyWhere it landed. Give the actionable set: a table of every open issue that is or after the sync, so the user sees at a glance what's being worked and what they can pick up next in a fresh worktree:
in-progressreadysh
gh issue list --state open --label in-progress --json number,title
gh issue list --state open --label ready --json number,title| # | Title | Status | Priority |
|---|---|---|---|
| 43 | | | high |
| 44 | | | medium |
List rows first, then , each group ordered by priority. If both sets are empty, say so instead of printing an empty table. Drop the column when no row carries one, because an all-blank column reads as "nothing matters" when the truth is "nobody has ranked these," and the fix for that is , not a wider table.
in-progressreadyPrioritytriageNext. Crown one row from that table, naming a kit only when it's installed: an issue is unfinished work and outranks a fresh start (resume it in its worktree with implementkit), while a one is the pick-up (). Priority orders within each group and doesn't jump a issue over an one, because finishing beats starting, and a half-built still costs less to land than a fresh . The exception is a , which means preempt by definition: crown it over in-progress work and say plainly what's being set down. Both sets empty means the tracker has nothing workable, so the move is from a plan, or plankit if there isn't one yet.
in-progressreadystart <n>readyin-progressmediumhighcriticalcreate变更内容:报告已关闭的issue、已修复的PR正文、已勾选的checklist、已更新或解锁(→)的issue,每个操作均需用户批准。如果无需修复任何内容,也需明确说明;无偏差的结果也是真实的成果。
blockedready当前状态:提供可操作集合:表格列出sync后所有处于或状态的打开issue,让用户一目了然当前正在处理的任务和可接手的新任务:
in-progressreadysh
gh issue list --state open --label in-progress --json number,title
gh issue list --state open --label ready --json number,title| # | 标题 | 状态 | 优先级 |
|---|---|---|---|
| 43 | | | high |
| 44 | | | medium |
先列出的issue,再列出的issue,每组按优先级排序。如果两组均为空,则说明情况而非打印空表格。当所有行均无优先级时,移除列,因为全空列会被误解为“所有任务都不重要”,而实际情况是“无人排序”,对应的解决方案是模式,而非扩大表格。
in-progressready优先级triage下一步操作:从表格中选择一个优先级最高的任务,仅当配套工具已安装时才提及工具名称:的issue是未完成的工作,优先级高于新任务(使用implementkit在其工作树中继续开发);的issue是可接手的新任务()。优先级仅在同一组内排序,不会让的issue优先于的issue,因为完成现有工作优于开始新工作,完成一半的任务比全新的任务成本更低。例外情况是优先级的任务,其定义就是优先处理:优先于正在进行的工作,并明确说明需要暂停当前工作。如果两组均为空,则说明追踪器中无可处理的任务,因此下一步是从规划创建issue,或使用plankit创建规划(如果没有规划)。
in-progressreadystart <n>readyin-progressmediumhighcriticalMode: triage
triage模式:triage
(梳理)
triageReport first, act on approval. Never mutate the tracker just to "tidy up."
先报告状态,获得批准后执行操作。绝不仅为“整理”而修改追踪器。
1. Read the tracker
1. 读取追踪器数据
Fetch (not just open), because detecting a closed parent with open children, or the inverse, needs the closed issues too. Filter to open for the drift that only concerns open work.
--state allsh
gh issue list --state all --limit 200 --json number,title,state,labels,assignees,updatedAt,createdAtParent→child hierarchy has two representations: a task-list () lives in the parent's body, but native sub-issue links live in the API, not the body, so enumerate them with rather than assuming the body tells the whole story.
- [ ] #childgh api repos/{owner}/{repo}/issues/{n}/sub_issues获取(不仅是打开状态)的issue,因为检测已关闭的父issue对应打开的子issue,或反之,需要已关闭的issue数据。对于仅关注打开任务的偏差,过滤为打开状态的issue。
--state allsh
gh issue list --state all --limit 200 --json number,title,state,labels,assignees,updatedAt,createdAt父→子层级有两种表示方式:任务列表()存在于父issue的正文中,但原生子issue链接存在于API中,而非正文,因此需使用枚举,而非假设正文包含全部信息。
- [ ] #childgh api repos/{owner}/{repo}/issues/{n}/sub_issues2. Flag drift
2. 标记偏差
Produce a status report, as a table, surfacing:
- Stale. No update in a long while (e.g. 30–60 days; scale to the repo's pace).
- Orphaned. No labels, no assignee, no parent.
- Closed-parent / open-children (and its inverse), meaning a broken hierarchy.
- Zombie label. A closed issue still carrying a status label (,
in-review, …) → strip it; the closed state is the signal.in-progress - Stale block. An issue labeled whose
blockedtarget is already closed → it should beBlocked by #N(hand the relabel toready).sync - Dangling / circular dependency. A pointing at a missing issue, or two issues blocking each other.
Blocked by #N - Unmarked. An open issue carrying no lifecycle label at all → offer to classify it (/
triage/needs-planning/ready).blocked - Unassessed. An open issue carrying no priority label → offer to rank it. Report this as its own count rather than folding it into Unmarked: the two are independent gaps, and a tracker with tidy lifecycle labels and no priorities anywhere is both a common state and an invisible one if the report only ever prints one number. Exclude and
wontfix, which need no rank.duplicate - Double-ranked. An open issue carrying more than one priority label → offer to keep the highest and drop the rest. This is the failure mode the one-at-a-time rule exists to prevent, and it happens whenever a label is set outside this skill (the GitHub UI applies labels additively, with nothing to stop it). Keeping the highest is the safe repair: it can only ever over-rank an issue the user is about to look at anyway, where silently keeping the lowest buries work somebody explicitly escalated.
- Stale . An issue labeled
criticalthat hasn't been updated in weeks → offer to demote it.criticalmeans preempt what's in progress, so an untouched one is self-refuting: nobody dropped anything for it, which is the tracker saying out loud that it isn't critical. Left alone it's worse than no label at all, because it outranks everything downstream forever and trains the user to ignore the level that's supposed to be unignorable. Scale "weeks" to the repo's pace, the same way the Stale check does.critical - Ungrilled . An issue labeled
readywhose decisions clearly aren't settled (open questions in the body, no acceptance criteria) → it was promoted too early; offer to move it back toreadyso unattended workers skip it until a human grills it.needs-planning - Missing labels, relative to the lifecycle map (or the repo's own scheme, if it predates it). When the map's labels aren't provisioned, say so and point at repokit rather than creating them.
- Status cross-checks. Issues whose linked PR merged but that are still open (hand off to for the actual close).
sync
生成状态报告,以表格形式展示:
- 过期:长时间未更新(例如30–60天;根据仓库节奏调整)。
- 孤立:无标签、无负责人、无父issue。
- 父issue已关闭/子issue仍打开(及反之),表示层级关系断裂。
- 僵尸标签:已关闭的issue仍携带状态标签(、
in-review等) → 移除标签;关闭状态本身就是信号。in-progress - 过期阻塞:标记为的issue,其
blocked的目标issue已关闭 → 应标记为Blocked by #N(将修改操作交给ready模式)。sync - 无效/循环依赖:指向不存在的issue,或两个issue互相阻塞。
Blocked by #N - 未标记:打开的issue未携带任何生命周期标签 → 提供分类选项(/
triage/needs-planning/ready)。blocked - 未评估:打开的issue未携带任何优先级标签 → 提供排序选项。将此作为单独的计数,而非合并到未标记中:这是两个独立的缺口,生命周期标签规范但无优先级的追踪器是常见状态,如果报告仅打印一个数字则会被忽略。排除和
wontfix状态的issue,这些无需排序。duplicate - 重复优先级:打开的issue携带多个优先级标签 → 保留最高优先级标签,移除其余标签。这是同一时间仅一个优先级标签规则要防止的故障模式,当通过GitHub UI设置标签时会出现这种情况(GitHub UI添加标签时不进行互斥检查)。保留最高优先级是安全的修复方式:仅可能让用户即将查看的issue优先级过高,而静默保留最低优先级会掩盖用户明确升级的任务。
- 过期:标记为
critical的issue数周未更新 → 提供降级选项。critical意味着优先于正在进行的工作,因此未被处理的criticalissue本身就不成立:无人暂停当前工作处理它,说明追踪器明确表示其并非critical。保留该标签比无标签更糟,因为它会永远优先于所有下游任务,导致用户忽略本应优先处理的级别。根据仓库节奏调整“数周”的定义,与过期检查一致。critical - 未审核的:标记为
ready的issue,其决策明显未敲定(正文中有未解决的问题、无验收标准) → 提前升级为ready;提供将其改回ready的选项,以便无人值守处理工具在人工审核前跳过该issue。needs-planning - 缺失标签,相对于生命周期映射(或仓库自身的规范,如果早于该映射)。当映射中的标签未配置时,说明情况并引导用户使用repokit,而非自行创建。
- 状态交叉检查:PR已合并但issue仍处于打开状态的情况(交给模式处理关闭)。
sync
3. Offer fixes
3. 提供修复方案
For each flagged item, propose a concrete fix (relabel, reprioritize, close as stale, post a decision comment) and apply only what the user approves:
sh
gh issue edit <n> --add-label <label>
gh issue edit <n> --add-label high --remove-label medium # priority is a replace, never an add
gh issue comment <n> --body-file <decision>
gh issue close <n> --comment "Closing as stale; reopen if still relevant."Ranking an unassessed backlog is a batch, so propose it as one table, with issue, title, and a proposed priority per row, rather than as one question per issue. Priority is comparative by nature: the user is deciding what beats what, and a table is the only shape that shows them the comparison they're actually making. Asked one at a time, twenty issues become twenty context-free judgments and every one of them comes back , which is the same as not ranking at all.
mediumPropose a distribution, not a wall of . A backlog where most things are has no priority information in it: the label stops discriminating and every consumer falls back to whatever tiebreak sits underneath it. Aim for a shape where is empty or nearly so, is a handful, and the long tail is and . When your own proposal comes out top-heavy, that's a signal to re-read the issues rather than to ship the table.
highhighcriticalhighmediumlowNever apply a priority the user didn't approve, even in a batch. Ranking is the one thing in this map that can't be derived from the tracker: every other triage fix repairs a state that's provably wrong (a zombie label on a closed issue, a block whose blocker landed), where a priority is a claim about what matters that only the user can make. Approve-the-table is fine; approve-nothing-and-apply-anyway is not.
对于每个标记的偏差,提出具体的修复方案(修改标签、重新排序、标记为过期关闭、添加决策注释),并仅执行用户批准的修复:
sh
gh issue edit <n> --add-label <label>
gh issue edit <n> --add-label high --remove-label medium # 优先级是替换操作,绝非添加
gh issue comment <n> --body-file <decision>
gh issue close <n> --comment "标记为过期关闭;如需重新处理请重新打开。"为未评估的待办事项排序是批量操作,因此以表格形式提出建议,每行包含issue编号、标题和建议的优先级,而非逐个询问。优先级本质上是相对的:用户需要判断任务的优先级顺序,表格是唯一能展示这种对比的形式。如果逐个询问,20个issue会变成20个无上下文的判断,且每个都会被标记为,与不排序效果相同。
medium建议合理的优先级分布,而非全部标记为。大部分任务为优先级的待办事项没有任何优先级信息:标签失去区分度,所有处理者都会退而求其次使用其他排序规则。目标是为空或几乎为空,为少数,大部分为和。如果自己的建议优先级过高,则需重新读取issue内容,而非直接提交表格。
highhighcriticalhighmediumlow绝不应用用户未批准的优先级,即使是批量操作。排序是唯一无法从追踪器推导的操作:其他梳理修复都是修复可证明错误的状态(已关闭issue的僵尸标签、依赖项已完成的阻塞issue),而优先级是关于任务重要性的判断,仅能由用户做出。批准表格是可行的;未批准却直接应用是不可行的。
4. Hand off
4. 交接
What changed. Report what the report found, and which fixes you applied versus left alone. A flagged item the user declined is worth naming; it stays drift until someone decides otherwise.
Where it landed. Give the tracker's state after the pass, per namespace: how many open issues now carry a lifecycle label and how many are still unmarked, and how many carry a priority and how many are still unassessed. Two numbers, because a pass can genuinely fix one and leave the other untouched.
Next. triage only classifies; the fixes it can't make itself belong to a sibling mode, so route by what survived: issues whose PR merged but that are still open → ; a stale whose prerequisite already landed → ; an issue promoted to too early → a human grill session (grillkit when installed) before anything unattended touches it; missing labels in either namespace → repokit. If the tracker came back clean, say so and point at the set, because the next move is on the highest-priority one, not more tidying.
syncblockedsyncreadyreadystart变更内容:报告发现的偏差,以及已执行和未执行的修复。用户拒绝的标记偏差需明确说明;该偏差会持续存在直到有人决定处理。
当前状态:提供梳理后的追踪器状态,按命名空间划分:打开的issue中携带生命周期标签的数量和仍未标记的数量,以及携带优先级标签的数量和仍未评估的数量。两个数字,因为一次梳理可能仅修复其中一个缺口,另一个保持不变。
下一步操作:triage模式仅负责分类,无法自行修复的问题需交给其他模式,因此根据剩余偏差引导:PR已合并但issue仍打开 → ;过期的issue其依赖项已完成 → ;提前升级为的issue → 人工审核会话(已安装grillkit时使用),然后才能进行无人值守处理;任一命名空间缺失标签 → repokit。如果追踪器梳理后无偏差,则说明情况并指向集合,因为下一步是启动最高优先级的issue,而非继续整理。
syncblockedsyncreadyreadyShared action: comment a plan or decision
共享操作:添加规划或决策注释
Across and you may post a plan excerpt or a decision onto an issue as an audit trail. It's a shared action, not a mode:
createtriagesh
gh issue comment <n> --body-file <file>Use a temp file for multi-line markdown and remove it after.
在和模式中,可能需要在issue中添加规划片段或决策作为审计记录。这是共享操作,而非独立模式:
createtriagesh
gh issue comment <n> --body-file <file>使用临时文件存储多行markdown,操作后删除临时文件。
Notes
备注
- Never merge PRs, and never mutate GitHub state without showing the change and getting an OK first.
- If the repo has its own issue conventions, whether a template in , a labeling scheme, or a title style visible in
.github/ISSUE_TEMPLATE/, follow those over these defaults and say you did.gh issue list - Prefer over
--body-filefor anything multi-line; clean up temp files afterward.--body - Keep issues proportional to the work: a one-line fix is one issue, not an epic with three children. Scale the breakdown to the plan's real surface area.
- 绝不合并PR,且绝不无提示修改GitHub状态,所有修改需先展示并获得用户批准。
- 如果仓库有自己的issue规范,例如中的模板、标签体系或
.github/ISSUE_TEMPLATE/可见的标题风格,则优先遵循仓库自身的规范,并告知用户已采用该规范。gh issue list - 多行内容优先使用而非
--body-file;操作后清理临时文件。--body - issue大小需与任务规模匹配:一行代码的修复对应一个issue,而非包含三个子issue的epic。根据规划的实际范围调整拆分方式。