mcpField
A
audit-ticket

audit-ticket

github.com/bhagyamudgal开发2102 次安装5 天前更新
代码仓库

关于 audit-ticket

audit-ticket 用于将 GitHub 旧 Issue 的要求与当前已提交代码快照逐项核对。它提供带代码证据的审计报告,并在用户选择后再更新、关闭、拆分或保留 Issue。

主要功能

  1. 01获取 Issue 正文和评论
  2. 02将附件图片纳入证据
  3. 03基于固定 Git 快照审计
  4. 04提供带代码引用的判定
  5. 05支持更新、关闭或拆分 Issue

适用场景

  1. 01规划前重新评估旧 Issue
  2. 02核实哪些要求已经实现
  3. 03识别过时或部分完成的请求
  4. 04准备有证据的 Issue 更新

安装

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

$npx skills add https://github.com/bhagyamudgal/skills --skill audit-ticket

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

附带文件references/execute.mdreferences/ticket-evidence.md

详细介绍

/audit-ticket:根据当前代码审查过时 issue

我会拿一条发布了数周或数月的 GitHub issue,逐项对照当前代码库检查其中的每项要求。旧工单会逐渐失效:一半的事项可能已在无关的 PR 中交付;有些会在重构后变得过时;其余事项则会悄无声息地阻碍规划,因为没人再相信这条工单。我会为每项给出判定和证据,然后由用户决定如何处理工单。我宁愿把这次审查一次做好,也不想再为这条工单争论一个季度。

用法

/audit-ticket 123
/audit-ticket https://github.com/owner/repo/issues/123
/audit-ticket            # no arg → ask for the issue number or URL

如果没有提供 issue,我会询问其编号或 URL。我绝不会根据当前分支、近期提交或未关闭的 issue 来推断。审查错工单会白白浪费一次完整的子 Agent 并行调用。

如果 URL 指向的仓库与 cwd 不同,我会在每次 gh 调用中传入 --repo <owner>/<repo>。如果 issue 所属仓库与要审查的代码不一致,我会先停下来确认要以哪个工作树为准。


阶段 1:接收信息(主流程)

在提取要求之前,我会完整阅读 ${CLAUDE_SKILL_DIR}/references/ticket-evidence.md。我会同时整理其中的来源映射和要求清单,以便后续重写或拆分时保留原始证据。

获取完整工单
gh issue view <n> --comments --json number,title,body,state,author,createdAt,updatedAt,labels,assignees,comments,url

我会获取所有评论,而不只是正文。后续评论经常会修改、缩小范围或删除正文中的要求。如果评论与正文矛盾,以评论为准,因为评论更新。

下载附加图片

我会从正文和每条评论中提取附件 URL。

  • https://github.com/user-attachments/assets/<id>
  • https://user-images.githubusercontent.com/...

对每个 URL,我都会使用身份验证下载,因为私有仓库的附件未经身份验证会返回 404;然后用 Read 读取文件,实际查看图片。

curl -fsSL -H "Authorization: token $(gh auth token)" -o /tmp/audit-ticket-<n>-img<i>.png "<url>"

-f 至关重要。没有它时,404 会以状态码 0 退出,并将错误正文写入 .png 文件;我可能会把非图片文件当作规格说明来 Read。我会在 Read 之前检查退出代码。

截图和模型图往往就是规格说明。正文中的 UI 模型图可能包含文字中未提及的要求。我会将图片所示内容纳入下方的要求清单。如果下载以非零状态码退出,我会在报告中注明 image <i> unavailable,而不是假装它不存在。

提取要求清单

我会按时间顺序浏览正文和评论,将每项独立的要求或主张编号为 R1..Rn。

  • 任务列表项,即 - [ ] 和 - [x]。我会保留其勾选状态,作为工单的“已有”主张,以供核实,而不是直接采信。
  • “添加 X”“修复 Y”“应当 Z”或“迁移到 W”之类的祈使表述。
  • 隐藏在评论中的验收标准和后续要求。
  • 附加模型图和截图中暗示的要求。

对每项,我都会记录 id、作为简短引文的 text、来源映射中的支持证据 E<n> ID,以及在后续评论修改了该要求时记录 superseded_by。重复项会合并。同一要求即使在三条评论中重述,仍只算一个 Rn,但我会在各自的证据 ID 下保留每条相关来源。

如果无法提取出任何要求,例如工单只有一句含糊的话,我会先询问用户具体要核实什么,再启动任何任务。

锚定审查对象

我会运行 git rev-parse HEAD 和 git rev-parse HEAD^{tree},并记录完整的提交 ID 和树 ID。我审查的是已提交的树。所有代码搜索、文件读取和行号引用都必须使用能指定快照的 Git 命令,例如 git grep <pattern> <tree-id> 和 git show <tree-id>:<path>,或对该确切树进行隔离检出。我不会触碰用户已暂存、未暂存或未跟踪的内容,也不会将其纳入审查。我会将这些内容标记为未检查,而不是将它们哈希进仓库对象数据库。

报告中的每项判定都会写明“截至 <full HEAD SHA>,已提交树为 <tree ID>”,以免后续提交和无关的本地工作悄然改变其证据。

第 2 阶段:调查(并行子 Agent)

我会为每项要求分配一个 general-purpose 子 Agent,并以每批 3-4 个的方式并行执行。主上下文充当协调者,不会自行 grep 来判断结果,这也能让各项判断保持独立。只有当两项要求涉及对同一文件进行相同修改时,我才会让它们共用一个子 Agent,例如“添加列”和“在 API 响应中公开该列”。

子 Agent 提示词
You are verifying ONE requirement from a stale GitHub issue against one
frozen code snapshot. The ticket is old. Code may have shipped, changed,
or made the requirement meaningless since it was written. Your job is a
verdict grounded in file:line evidence, not a guess.

## Ticket context
Issue: #<n>, <title> (opened <createdAt>)
Goal (1 sentence): <from body>
HEAD: <full Phase 1 SHA>
Content snapshot: <verified_content_snapshot tree hash>

## Requirement to verify
<Rn>: <requirement text>
Source: <body | comment | image>
<superseded_by note, if any>

## Your task
1. Search only the recorded content snapshot with snapshot-aware Git
   commands (`git grep <pattern> <tree>` and `git ls-tree -r <tree>`).
   Search by behavior keywords, not just the exact names the ticket uses.
2. Read matches with `git show <tree>:<path>` and derive line numbers from
   those bytes. Decide whether the requirement is implemented,
   partially implemented, absent, or no longer applicable, meaning the code it
   targeted was removed or rewritten, or a different approach shipped.

## Output format (exactly this)
verdict: done | partially-done | not-done | obsolete
confidence: high | medium | low
evidence:
  - <file:line>: <what this line shows, one clause>
  - ...
gaps: <REQUIRED for partially-done/not-done. What's still missing, specific>
obsolete_reason: <REQUIRED for obsolete. What changed and where (file:line)>

## Rules
- Every done/partially-done verdict MUST cite at least one file:line.
- "obsolete" needs evidence of the superseding change, not a hunch.
- If you genuinely cannot determine it, say verdict: not-done with
  confidence: low and explain what you'd need.
降级模式规则

子 Agent 失败或返回空结果不会中止审计。我会在报告中将该要求标记为 unverified 并继续。只有当所有子 Agent 都失败时,我才会中止。


第 3 阶段:报告(主流程)

打印前,我会通过读取 git show <verified_content_snapshot>:<path> 中所引用的范围,确认返回的每个 file:line 都存在于记录的内容快照中。我会删除伪造的引用,并将对应判断的置信度降为 low。

表格中会且只会出现一次第 1 阶段的每个 Rn。N 等于 d + p + nd + o + u。没有返回判断结果的要求标记为 unverified,不会省略。我只在表格单元格中放置证据 ID,然后在块格式的来源映射中列出每条完整的 Rn → E<n> 关联。代码引用仍作为独立的判断证据。

接手此工单的人会阅读这份审计报告,第 5 阶段也可能会将其原样发布到 GitHub。报告中不使用 em dash 或 en dash。如果已安装 unslop,其余规则由它负责。

然后我会打印以下内容。

# Ticket audit: <title> (#<n>)

**State**: <open|closed> · opened <date> · last activity <date>
**Audited against**: <full HEAD SHA> at content snapshot <tree hash> on <today>
**Requirements**: <N> total, <d> done / <p> partial / <nd> not done / <o> obsolete / <u> unverified
**Recommendation**: <one sentence, grounded in the verdict mix>

| # | Requirement | Source evidence | Verdict | Code evidence |
|---|-------------|-----------------|---------|---------------|
| R1 | <short text> | E1 | ✅ done | `<file:line>` |
| R2 | <short text> | E2, E4 | 🟡 partial | `<file:line>`: <gap, short> |
| R3 | <short text> | E3 | ❌ not done | none |
| R4 | <short text> | E5 | 🪦 obsolete | <reason, short> |

## Source evidence map

### R1 → E1
**Source**: <author> · <date> · <direct URL>

    <complete exact excerpt; indent every original line so multiline text and pipes remain intact>

<repeat one block for every Rn → E<n> edge>

## Details
<per-item: full gaps, obsolete reasons, low-confidence notes, unavailable images>

我的建议逻辑如下。

  • 全部已完成或已过时 → 我建议结束处理;大部分已完成时标记为 completed,大部分已过时时标记为 not planned。
  • 有些事项已完成,有些仍未处理 → 我建议原地更新,即发表评论并编辑正文。
  • 尚无事项完成,且仍然有效 → 我建议原地更新,并添加“仍全部待处理,已于 重新分诊”的备注;如果工单正文已经准确,则保持不变。

第 4 阶段:决定(AskUserQuestion)

header: "Ticket fate"
text: "Audit of #<n>: <d> done, <p> partial, <nd> not done, <o> obsolete. What should happen to it?"
options:
  - "Update in place (Recommended)": Post the audit as a status comment and edit the body into an accurate current checklist
  - "Sunset (close)": Post the audit reasoning as a comment and close as <completed | not planned>
  - "Split remainder": File a follow-up issue with only the open items (assigned to you), link it, close this one
  - "Leave unchanged": Keep the report local; ticket untouched

当每项要求都已完成或已过时时,我会调整选项顺序。“结束处理(关闭)”会排在第一位,并标记为“(推荐)”。更新一份已无待办事项的正文只会造成无谓改动。


第 5 阶段:执行(gh)

第 5 阶段根据第 4 阶段选择的处理方式执行,且只依据该选择执行。报告始终可以安全打印,但每项 gh 写入操作都必须等待用户明确选择。我会读取 ${CLAUDE_SKILL_DIR}/references/execute.md 中所选处理方式对应的操作方案。

对于任何重写或拆分,在撰写工单正文前,以及再次执行其渲染后的关闭检查关卡时,我都会重新读取 ${CLAUDE_SKILL_DIR}/references/ticket-evidence.md。缺少必需来源证据时,所选处理方式不能关闭工单。

在撰写或冻结第 5 阶段的载荷之前,我会立即重新运行 git rev-parse HEAD 和 git rev-parse HEAD^{tree},然后将两个确切值与第 1 阶段的提交 ID 和树 ID 进行比较。我不会触碰用户的暂存索引和工作树。如果任一值发生变化,我会找出所有代码证据或判断可能受到新提交字节影响的要求,针对新树通过第 2 阶段重新处理这些要求,使用两个新标识符重建第 3 阶段报告,然后返回第 4 阶段重新征求批准。如果无法界定受影响的范围,我会重新处理所有要求。

随后,我会重新获取完整的工单正文和评论,并重新下载所有保留的附件。我会将 updatedAt、正文、评论 ID 和内容、附件 URL 以及附件摘要与第 1 阶段的内容进行比较。如果任何来源发生变化,或无法确认其时效性,我会重建来源映射,保留匹配的证据 ID,为新证据追加 ID,并通过第 2 和第 3 阶段重新处理所有受影响的要求。如果无法获取必需证据,我会停止。在拆分流程创建后渲染之前,我会再次执行代码和来源时效性检查关卡。若审计提交或树、要求、判断、建议、后续工单范围或处理方式发生变化,则返回第 4 阶段重新征求批准。 每个已冻结的正文或评论都包含其提及的每项要求的 Rn → E<n> 映射和块形式的保留摘录。前置任务状态、推理、编辑后的正文和拆分评论载荷包含完整映射。后续任务包含其迁移要求对应的映射。

对于原位更新或结束,我会在预检前渲染所有最终正文和评论。我会提供其确切的冻结字节和 SHA-256 摘要、当前目标保护信息,以及供用户明确批准的有序操作。我会将批准绑定到这些值,以及源证据、范围、判定、建议和处置方式。任何变更都会使批准失效。

对于拆分,我会将不可重复的创建状态绑定到一个现有且持久的账本,并且用户已授权写入该账本。在创建前,我会写入一条尝试记录,其中包含操作 ID、冻结的后续任务载荷路径和摘要、前置任务保护信息、预期标题、指派对象,以及 --label ai-created;协调状态为 planned,并预留稳定的后续任务 ID、URL 和保护信息字段。如果不存在已授权且可写的账本,我会将拟议记录保留在行内,并在创建前停止。我不会启动多卡片拆分。

首先,我会协调每条 attempting、reconcile-required 或 landed 记录。只有当记录为 planned 且此前没有进行过不可重复的尝试时,我才会渲染并预检创建操作;并且必须先完成 file-issue 的双词汇重复项搜索和 ai-created 标签初始化。我会在执行 gh issue create 前立即持久化 attempting 状态。结果不明确时,状态会变为 reconcile-required,绝不会重试。一旦权威回读确认后续任务已带有 ai-created 标签,我会填写其稳定 ID、URL、冻结载荷摘要和保护信息,然后将记录标记为不可重复的 landed 部分状态。每次重新进入流程时,我都会重新获取并复用该后续任务,绝不会再次调用创建操作。

对于每张变更卡片,我会记录每个载荷路径和 SHA-256 摘要、确切标题、标签和命令选项、最新目标保护信息,以及每一步预期的保护信息转换。在该卡片首次写入前,我会立即将确切目标、审计提交和树 ID、有序操作、第 4 阶段批准及拆分元数据传给 preflight-mutations。后续每次写入前,我只会根据上一次写入的权威回读更新保护信息。

后续任务创建完成后,我会执行源信息时效性检查,然后使用真实的后续任务 URL 渲染并冻结前置任务评论。我会就该评论的确切字节和摘要、当前前置任务与后续任务的保护信息,以及预期评论保护信息转换的有序评论和关闭操作,重新获取明确批准。权威回读确认确切评论已发布后,我会将状态更新为返回的预期保护信息,并允许关闭,无需重新审批。任何意外的状态转换,或外部保护信息、源证据、载荷字节、范围、判定、建议或处置方式发生变化,都会使批准失效。我会通过明确的保留、编辑或关闭计划协调已创建的后续任务;语义发生变化时,我会返回第 4 阶段。我绝不会重新创建后续任务。


错误处理

  • 未安装 gh。我会立即停止,并提示 Install gh CLI: https://cli.github.com。
  • 已安装 gh,但未通过身份验证。我会立即停止,并提示 Run 'gh auth login' and retry.
  • 找不到问题或无权访问。我会报告 Couldn't access issue #<n>. Check the number and repo access.
  • 问题已关闭。我仍会执行审计,因为用户可能想验证关闭状态或重新打开问题,并会在报告中醒目注明 State: closed。对于“原位更新”,我会询问是否也要重新打开问题。

评论

支持 Markdown