review-tickets

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
<!-- markdownlint-disable-file MD041 -->
STARTER_CHARACTER = 🧾
<!-- markdownlint-disable-file MD041 -->
STARTER_CHARACTER = 🧾

Review Tickets

审阅工单

Turn a review-deep, review-full, or review-diff run into ticket files that a person or a model can act on without re-reading the review. Every sentence in a ticket is a reviewer's own sentence, kept, narrowed, or deleted by a judge that read the code. The only new text is the Summary.
The input is a review-deep, review-full, or review-diff run directory. It holds
run.json
,
findings.jsonl
,
issues.jsonl
,
verify/results.jsonl
,
verify/second.jsonl
, and
checkout/
, a clean checkout of the reviewed commit. Everything this skill writes goes under
<run>/tickets/
. The scripts are in
scripts/
next to this file and use the Python standard library, except
dupscreen.py
, which runs through
uv
.
将一次 review-deep、review-full 或 review-diff 运行转换为工单文件,使人或模型无需重读审查内容即可据此行动。工单中的每一句话都来自审阅者本人,由读过代码的 judge 决定保留、收窄或删除。唯一新增的文字是 Summary。
输入是一次 review-deep、review-full 或 review-diff 运行的目录。其中包含
run.json
、
findings.jsonl
、
issues.jsonl
、
verify/results.jsonl
、
verify/second.jsonl
和
checkout/
,后者是被审阅 commit 的干净 checkout。此 skill 写入的所有内容都位于
<run>/tickets/
下。脚本位于本文件旁边的
scripts/
中,并使用 Python 标准库,只有
dupscreen.py
通过
uv
运行。

Arguments

参数

The run directory printed by review-deep, review-full, or review-diff. Every command below uses it as
$RUN
. If the invocation gave no run directory, Step 1 auto-discovers it when exactly one candidate exists; it does not stop to ask.
由 review-deep、review-full 或 review-diff 打印的 run 目录。以下每条命令都将其用作
$RUN
。如果调用时未提供 run 目录,且恰好存在一个候选项,Step 1 会自动发现它;不会停下来询问。

Requirements

要求

  • claude
    on
    PATH
    , logged in to a provider. Each judge is a
    claude -p
    process that inherits this environment, so model aliases such as
    opus
    and
    fable
    resolve through the same provider settings as the invoking session.
  • git
    , and the repository at
    run.json
    repo
    with the reviewed commit present.
  • uv
    for the duplicate screen.
run.json
sets the models as
[alias, effort]
pairs under
models
. Defaults are
judge
Opus at xhigh,
critical
Fable at high, and
sibling
Opus at xhigh.
concurrency
defaults to 50.
  • claude
    位于
    PATH
    中,并已登录某个提供商。每个 judge 都是一个
    claude -p
    进程,会继承此环境,因此
    opus
    和
    fable
    等模型别名会通过与调用会话相同的提供商设置进行解析。
  • git
    ,以及
    run.json
    中
    repo
    指向的仓库;被审阅的 commit 必须仍然存在。
  • uv
    ,用于重复项筛查。
run.json
在
models
下将模型设置为
[alias, effort]
对。默认配置为:judge 使用 xhigh 级别的 Opus,critical 使用 high 级别的 Fable,sibling 使用 xhigh 级别的 Opus。
concurrency
默认为 50。

Procedure

操作流程

Run each model step as a background Bash call. The pool returns when every call has finished, and the completion notification is the signal to continue. Never poll a running step with
sleep
. Run the step command itself as the background call. Never detach it with
nohup
or a trailing
&
, and never wait on a log line with
tail -f | grep -m1
.
tail
exits only when it next writes, so the call hangs until its timeout once the log gets its last line.
将每个模型步骤作为后台 Bash 调用运行。调用池会在所有调用完成后返回,而完成通知就是继续执行的信号。绝不要使用
sleep
轮询正在运行的步骤。应将步骤命令本身作为后台调用运行。绝不要用
nohup
或末尾的
&
将其脱离,也绝不要在日志行上等待
tail -f | grep -m1
。
tail
只有在下一次写入时才会退出,因此日志出现最后一行后,调用会一直挂起直至超时。

Step 1: Preflight and Plan

Step 1:预检与规划

bash
S="${CLAUDE_SKILL_DIR}/scripts"   # replace ${CLAUDE_SKILL_DIR} with this SKILL.md's own directory on a non-Claude harness
[ -f "$S/plan.py" ] || { echo "scripts not found at $S"; exit 1; }
PF="${CLAUDE_SKILL_DIR}/../review-deep/scripts"   # preflight.py has one copy, in review-deep
[ -f "$PF/preflight.py" ] || { echo "scripts not found at $PF"; exit 1; }

RUN="<user-provided run directory, or empty>"
if [ -z "$RUN" ]; then
  cache="${XDG_CACHE_HOME:-$HOME/.cache}"
  candidates=$(find "$cache/review-deep" "$cache/review-full" "$cache/review-diff" -mindepth 1 -maxdepth 1 -type d 2>/dev/null \
    | while read -r d; do [ -f "$d/run.json" ] && echo "$d"; done)
  n=$(printf '%s\n' "$candidates" | grep -c .)
  if [ "$n" -eq 1 ]; then
    RUN="$candidates"
    echo "no run directory given, one candidate exists, using $RUN"
  else
    echo "no run directory given and $n candidates exist, name one explicitly:"
    printf '%s\n' "$candidates"
    exit 1
  fi
fi

python3 "$PF/preflight.py" --tier tickets --run "$RUN" || exit 1

python3 $S/plan.py "$RUN"
preflight.py --tier tickets
checks that
run.json
exists, that the repository and the reviewed commit both still exist (a commit can be pruned by
git gc
two weeks after a snapshot run, per review-full and review-diff's
init_run.py
), and that
checkout/
,
issues.jsonl
, and
verify/results.jsonl
are all present, since any of the three input kinds must have finished review-deep's Step 5 chain before ticketing starts. The
$S
guard catches a partial or corrupted plugin or skill install.
An issue is planned when its review rating is at or above the floor, High by default, and the verifier confirmed it. Its ticket severity is the lower of the verifier's and the second check's ratings, even below the floor.
tickets/decisions.json
can list
skip_issues
, for issues already tracked elsewhere, and
include_issues
, for issues whose first verdict is unusable, such as a placeholder answer. The judge verifies included issues itself.
bash
S="${CLAUDE_SKILL_DIR}/scripts"   # replace ${CLAUDE_SKILL_DIR} with this SKILL.md's own directory on a non-Claude harness
[ -f "$S/plan.py" ] || { echo "scripts not found at $S"; exit 1; }
PF="${CLAUDE_SKILL_DIR}/../review-deep/scripts"   # preflight.py has one copy, in review-deep
[ -f "$PF/preflight.py" ] || { echo "scripts not found at $PF"; exit 1; }

RUN="<user-provided run directory, or empty>"
if [ -z "$RUN" ]; then
  cache="${XDG_CACHE_HOME:-$HOME/.cache}"
  candidates=$(find "$cache/review-deep" "$cache/review-full" "$cache/review-diff" -mindepth 1 -maxdepth 1 -type d 2>/dev/null \
    | while read -r d; do [ -f "$d/run.json" ] && echo "$d"; done)
  n=$(printf '%s\n' "$candidates" | grep -c .)
  if [ "$n" -eq 1 ]; then
    RUN="$candidates"
    echo "no run directory given, one candidate exists, using $RUN"
  else
    echo "no run directory given and $n candidates exist, name one explicitly:"
    printf '%s\n' "$candidates"
    exit 1
  fi
fi

python3 "$PF/preflight.py" --tier tickets --run "$RUN" || exit 1

python3 $S/plan.py "$RUN"
preflight.py --tier tickets
会检查
run.json
是否存在、仓库和被审阅的 commit 是否仍然存在,以及
checkout/
、
issues.jsonl
和
verify/results.jsonl
是否全部存在。根据 review-full 和 review-diff 的
init_run.py
,快照运行两周后 commit 可能会被
git gc
清理;而上述三个输入中的任何一个,都必须先完成 review-deep 的 Step 5 链路,才能开始创建工单。
$S
检查可发现插件或 skill 安装不完整或已损坏的情况。
当 issue 的审查评级达到或高于门槛(默认是 High),且 verifier 已确认该 issue 时,它就会被纳入计划。其工单严重级别取 verifier 评级和 second check 评级中的较低者,即使该值低于门槛。
tickets/decisions.json
可以列出
skip_issues
,用于已在其他地方跟踪的 issue;也可以列出
include_issues
,用于首次判定不可用的情况,例如占位回答。judge 会自行验证被纳入的 issue。

Step 2: Re-cut into units

Step 2:按文件重新拆分

bash
python3 $S/recut.py $RUN
A unit is one issue's findings in one file. A themed issue that merged 77 findings across 24 files produced tickets whose cited locations did not support the claim. Per-file units fixed that, and Step 4 merges units back only when one change fixes them.
bash
python3 $S/recut.py $RUN
一个 unit 是单个 issue 在单个文件中的发现。一个跨 24 个文件合并了 77 项发现的主题性 issue 曾生成工单,但工单中引用的位置并不能支持相应论断。按文件划分 unit 解决了这个问题,而 Step 4 仅在某一次更改能够解决多个 unit 时才将其重新合并。

Step 3: Judge and edit

Step 3:判断与编辑

bash
python3 $S/judge.py $RUN              # every unit, background
python3 $S/apply.py $RUN
python3 $S/judge.py $RUN --critical   # second model on units still Critical, background
python3 $S/apply.py $RUN
The judge reads the code, tries to refute every claim, and returns each finding as keep, edit, or delete. A keep must name the code behind each of its claims. An edit changes only what the code contradicts. Every edit and delete cites code, and a script checks each quote against git at the reviewed commit before the answer is accepted.
apply.py
writes
tickets/edits.json
. A unit is excluded when the judge refutes it, when the second model disagrees on the verdict, or when a quote is not the code.
judge.py --ids FILE
reruns a JSON list of unit IDs and keeps every other answer.
bash
python3 $S/judge.py $RUN              # every unit, background
python3 $S/apply.py $RUN
python3 $S/judge.py $RUN --critical   # second model on units still Critical, background
python3 $S/apply.py $RUN
judge 会读取代码,尝试反驳每项论断,并将每项发现返回为 keep、edit 或 delete。每条 keep 都必须指出其各项论断背后的代码。edit 只修改代码与之矛盾的部分。每次 edit 和 delete 都会引用代码;在接受回答前,脚本会将每段引文与 git 中被审阅 commit 的代码进行核对。
apply.py
会写入
tickets/edits.json
。当 judge 驳回某个 unit、第二个模型不同意其判定,或某段引文与代码不符时,该 unit 会被排除。
judge.py --ids FILE
会重新运行一组 JSON 列表中的 unit ID,并保留其他所有回答。

Step 4: Merge siblings that share one fix

Step 4:合并共享同一修复的同级 unit

bash
python3 $S/siblings.py $RUN           # background
python3 $S/judge.py $RUN --merged     # background
python3 $S/apply.py $RUN --merged
Splitting by file also splits one defect seen from a caller and its callee. For every issue with two or more ready units, a judge groups the units whose defect one change at a single location resolves. The same pattern in two independent places stays two tickets. A merged ticket is then judged again as a whole, which checks its new Summary and can edit its findings. A merged ticket keeps every finding as its own bullet, so a caller and a callee both appear.
bash
python3 $S/siblings.py $RUN           # background
python3 $S/judge.py $RUN --merged     # background
python3 $S/apply.py $RUN --merged
按文件拆分也会把一个从调用方及其被调用方观察到的缺陷拆开。对于每个包含两个或更多 ready unit 的 issue,judge 会对 unit 分组:只有当同一位置的一次更改能够解决这些 unit 的缺陷时,才将它们归为一组。相同模式出现在两个独立位置时,仍保留为两个工单。合并后的工单会再次作为整体接受 judge 检查,这会检查其新的 Summary,并可编辑其 findings。合并后的工单仍将每项发现保留为独立的项目符号,因此调用方和被调用方都会出现。

Step 5: Assemble and check

Step 5:组装与检查

bash
python3 $S/assemble.py $RUN
python3 $S/checks.py $RUN
assemble.py
also writes
tickets.md
next to
report.md
in the run directory: the same tickets as plain markdown, opening with a count of tickets by perspective and priority, then every ticket in priority order with its findings and code. Rerunning Step 5 after Step 7 rewrites it.
checks.py
must print
problems 0
before anything is posted. It compares every code block to git byte for byte, checks every location, and flags markup Jira will not render.
bash
python3 $S/assemble.py $RUN
python3 $S/checks.py $RUN
assemble.py
还会把
tickets.md
写到 run 目录中的
report.md
旁边:内容与工单相同,只是采用纯 Markdown 格式,开头给出按视角和优先级统计的工单数,随后按优先级列出每个工单及其 findings 和代码。Step 7 之后重跑 Step 5 会重写该文件。
在发布任何内容之前,
checks.py
必须打印
problems 0
。它会将每个代码块与 git 逐字节比对,检查每个位置,并标记 Jira 无法渲染的标记语法。

Step 6: Screen for duplicates

Step 6:筛查重复项

Export the target project's issues with any Jira client as JSON, one object per issue with
key
,
summary
, and
description
, at the top level or under
fields
. Then:
bash
uv run --with scikit-learn --with numpy python $S/dupscreen.py $RUN existing.json
The screen prints pairs by shared vocabulary for a person to read. Most pairs share a topic, not a defect.
使用任意 Jira 客户端将目标项目的 issues 导出为 JSON,每个 issue 一个对象,包含
key
、
summary
和
description
,这些字段可以位于顶层或
fields
下。然后运行:
bash
uv run --with scikit-learn --with numpy python $S/dupscreen.py $RUN existing.json
该筛查会按共享词汇打印配对,供人工阅读。大多数配对共享的是主题,而不是缺陷。

Step 7: Record decisions

Step 7:记录决定

Write the operator's decisions to
tickets/decisions.json
and rerun Step 5.
KeyEffect
drop
{ID: reason}
. The ticket is removed, for example as a duplicate of an existing issue.
defer_priorities
A list such as
["Low"]
. Those tickets stay assembled and checked but leave
tickets/postable.json
.
skip_issues
,
include_issues
Read by Step 1.
将操作者的决定写入
tickets/decisions.json
,然后重跑 Step 5。
键效果
drop
{ID: reason}
。移除该工单,例如将其判定为现有 issue 的重复项。
defer_priorities
诸如
["Low"]
的列表。这些工单仍会完成组装和检查,但不会进入
tickets/postable.json
。
skip_issues
、
include_issues
由 Step 1 读取。

Step 8: Post

Step 8:发布

Post only after the operator's explicit go. Use whichever Jira client is available. The rules below held on 385 tickets.
  • Post one ticket at a time, in priority order. Map Critical to Highest, High to High, Medium to Medium, and Low to Low. Send the
    summary
    , the
    type
    , the mapped priority, the
    labels
    , and the
    description
    as Jira wiki markup.
  • Append the ticket ID and the new key to a log the moment the create call returns, before anything else.
  • Read every ticket back with its description as ADF and run
    python3 $S/readback.py TICKET_JSON FIELDS_JSON
    . Stop on the first mismatch. One run stopped when two code spans joined by an en dash rendered as a single span. The checker caught it before the next 300 tickets repeated it.
  • Stop on the first error. Retry only a 429, after its Retry-After wait. A timeout or a 5xx may have created the issue, so reconcile before retrying.
  • Before any resume, reconcile the log against a search for the run's ticket label (
    review-deep
    ,
    review-full
    , or
    review-diff
    , read from
    run.json
    ). Jira search leaves out archived issues, so an issue archived on purpose never counts as a stray.
  • Post the first ticket alone, read it back field by field, and continue only after it matches.
只有在操作者明确同意后才能发布。使用任意可用的 Jira 客户端。以下规则已在 385 个工单上得到验证。
  • 每次只发布一个工单,并按优先级排序。将 Critical 映射为 Highest,High 映射为 High,Medium 映射为 Medium,Low 映射为 Low。以 Jira wiki 标记发送
    summary
    、
    type
    、映射后的优先级、
    labels
    和
    description
    。
  • 在 create 调用返回的当下,先将工单 ID 和新 key 追加到日志,然后才进行其他操作。
  • 将每个工单连同其 ADF 格式的 description 读回,并运行
    python3 $S/readback.py TICKET_JSON FIELDS_JSON
    。遇到第一个不匹配时立即停止。有一次运行中,两个由 en dash 连接的代码 span 被渲染成一个 span,导致运行中止。检查器在后续 300 个工单重复此问题之前便捕获了它。
  • 遇到第一个错误时立即停止。仅在收到 429 后按照
    Retry-After
    等待再重试。超时或 5xx 可能已经创建了 issue,因此重试前必须先进行核对和协调。
  • 恢复运行前,将日志与针对该 run 工单标签的搜索结果进行协调核对;标签从
    run.json
    中读取,值为
    review-deep
    、
    review-full
    或
    review-diff
    。Jira 搜索不会返回已归档的 issue,因此有意归档的 issue 不会被视为意外创建的工单。
  • 先单独发布第一个工单,逐字段读回,只有完全匹配后才继续。

Step 9: Bundle deferred tickets

Step 9:打包延期工单

bash
python3 $S/bundle.py $RUN
tickets/bundle/ticket.json
describes one ticket for all deferred work, with every category label, and
tickets/bundle/<name>-deferred-defects.md
holds each deferred ticket's summary, categories, and findings. Post the ticket, attach the file, and compare the downloaded attachment with the local file byte for byte.
bash
python3 $S/bundle.py $RUN
tickets/bundle/ticket.json
描述一个涵盖所有延期工作的工单,其中包含每个 category 标签;
tickets/bundle/<name>-deferred-defects.md
保存每个延期工单的 summary、category 和 findings。发布该工单,附加文件,并将下载的附件与本地文件逐字节比较。

Jira wiki markup

Jira wiki 标记

The assembler handles these, and
checks.py
flags any it misses. Each was found by posting and reading back.
  • Inside
    {{...}}
    , Jira drops the escaping backslash before
    { } [ ] * | !
    and keeps it before anything else, so
    {{"a\"b"}}
    shows
    "a\"b"
    .
  • A code span holding only a backslash has no working encoding.
    {{\}}
    loses the monospace,
    {{\\}}
    shows two backslashes, and
    &#92;
    stays undecoded. The assembler writes the word backslash.
  • Jira closes
    {{...}}
    only next to certain characters. The confirmed ones are a space,
    , / . ' - ; )
    , and a newline after a span, and a space,
    /
    ,
    (
    , and a newline before one. The assembler puts a space between a span and any other neighbor.
  • A markdown backtick run pairs only with a run of the same length. A literal
    ```json
    in a finding stays text.
  • Code languages outside
    javascript json yaml bash python sql csharp
    are written as
    none
    , because no other language name was seen rendering.
组装器会处理以下情况,
checks.py
会标记任何遗漏。每一项情况都是通过发布并读回发现的。
  • 在
    {{...}}
    内部,Jira 会丢弃位于
    { } [ ] * | !
    前的转义反斜杠,但会保留其他字符前的反斜杠,因此
    {{"a\"b"}}
    会显示为
    "a\"b"
    。
  • 仅包含一个反斜杠的代码 span 没有可行的编码方式。
    {{\}}
    会丢失等宽格式,
    {{\\}}
    会显示两个反斜杠,而
    &#92;
    不会被解码。组装器会写入单词 backslash。
  • Jira 只有在紧邻某些字符时才会关闭
    {{...}}
    。已确认的情况是:span 后面为空格、
    , / . ' - ; )
    或换行,或者 span 前面为空格、
    /
    、
    (
    或换行。组装器会在 span 与任何相邻内容之间放入一个空格。
  • Markdown 中连续的 backtick 只有长度相同时才会配对。finding 中原样出现的
    ```json
    会保持为文本。
  • javascript json yaml bash python sql csharp
    之外的代码语言会写为
    none
    ,因为没有观察到其他语言名称能够正常渲染。

What the settings are based on

这些设置的依据

SettingEvidence
Opus at xhigh as the judgeOn 10 units holding 10 known wrong sentences, Opus xhigh removed 10 of 10 for $3.84, Fable at medium 10 of 10 for $6.93, Fable at high 10 of 10 for $9.65, and Opus at high 9 of 10 for $1.72. On the full run, 618 units took 17 minutes and $188.59 at list price with 50 concurrent.
A reason on every keepEvery wrong sentence that survived a judge was a keep with an empty reason. A re-judge of the 291 units with such keeps, under the rule, cost $98.49.
Isolated
claude -p --bare
processes
Workflow subagents received the operator's CLAUDE.md, skill listing, MCP instructions, and hooks. A Serena hook denied their reads, and the CLAUDE.md prose rules changed punctuation inside quoted code. A bare process starts with about 3,000 tokens of context, against 77,000.
--tools Bash,Read
under
dontAsk
--bare
has no Grep or Glob, and asking for them yields Read alone, which hid search from a whole run. Search runs through Bash, read-only commands run, and writes are denied.
cd
,
awk
,
xargs
,
cut
,
node
, variable assignment, and
$(...)
were denied in practice, so the prompt names them.
A 5-minute prompt cacheWith
ENABLE_PROMPT_CACHING_1H
set, every cache write was billed at the 1-hour rate, twice the input price. The pool removes it and sets
CLAUDE_CODE_PROMPT_CACHE_TTL=5m
.
A content check on every answerA JSON schema checks shape. Models answered schema rejections with placeholders such as
reason: "test"
and evidence
a:1
, and quoted code with dropped type annotations and rewritten punctuation.
One process per ticket, not one long sessionA session judging many tickets rereads its whole growing context every turn. A per-ticket session ends near 26,000 tokens.
A clean checkout of the commitJudges that searched the live tree read other reviewers' findings from the review state directory. The checkout also drops the files listed in
run.json
judge_exclude
, such as
CLAUDE.md
and
.claude/
.
The lower of two ratingsThe operator's rule. Judges rate lower than reviewers, and on one 618-unit production run 459 units moved down.
设置依据
将 Opus at xhigh 用作 judge在包含 10 个已知错误句子的 10 个 unit 上,Opus xhigh 以 $3.84 删除了 10/10,Fable at medium 以 $6.93 删除了 10/10,Fable at high 以 $9.65 删除了 10/10,而 Opus at high 以 $1.72 删除了 9/10。在完整运行中,以 50 并发处理 618 个 unit 耗时 17 分钟,按标价花费 $188.59。
每条 keep 都必须有 reason每个在 judge 审查后仍被保留的错误句子,都是一条 reason 为空的 keep。对 291 个包含此类 keep 的 unit 按该规则重新 judge,花费了 $98.49。
隔离的
claude -p --bare
进程
工作流 subagent 会收到操作者的 CLAUDE.md、skill 清单、MCP 指令和 hooks。Serena hook 拒绝读取,而 CLAUDE.md 中的散文规则改动了引用代码里的标点。bare 进程启动时约有 3,000 tokens 上下文,而原会话为 77,000。
在
dontAsk
下使用
--tools Bash,Read
--bare
没有 Grep 或 Glob,而请求它们只会得到 Read,这使整次运行都无法搜索。搜索通过 Bash 执行;只读命令可以运行,写入则被拒绝。
cd
、
awk
、
xargs
、
cut
、
node
、变量赋值和
$(...)
在实际运行中均被拒绝,因此 prompt 会明确列出它们。
5 分钟 prompt 缓存设置
ENABLE_PROMPT_CACHING_1H
后,每次缓存写入都按 1 小时费率计费,是输入价格的 2 倍。调用池会移除该设置,并设置
CLAUDE_CODE_PROMPT_CACHE_TTL=5m
。
对每个回答执行内容检查JSON schema 会检查结构。模型在 schema 拒绝后给出了
reason: "test"
和 evidence
a:1
等占位内容,并引用了丢失类型注解、重写标点的代码。
每个工单使用一个进程,而不是一个长会话判断许多工单的会话每轮都会重读不断增长的整个上下文;每个工单单独的会话结束在约 26,000 tokens。
使用被审阅 commit 的干净 checkout搜索实时工作树的 judge 会从 review state 目录中读到其他审阅者的 findings。checkout 还会移除
run.json
中
judge_exclude
列出的文件,例如
CLAUDE.md
和
.claude/
。
取两个评级中的较低者这是操作者制定的规则。judge 给出的评级通常低于审阅者;在一次包含 618 个 unit 的生产运行中,有 459 个 unit 的评级被下调。

Reporting counts

计数报告

A ticket carries one category label for every perspective that raised any of its findings, and most tickets carry more than one. In a table of tickets by category and priority, the category rows count labels, so they add up to more than the number of tickets. Label the rows as tickets carrying that category, and give distinct tickets as a separate total.
每个提出过任意 finding 的视角都会在工单上获得一个 category 标签,而且大多数工单不止一个。在按 category 和优先级统计工单的表格中,category 行统计的是标签数,因此总和会超过工单总数。应将这些行标为“携带该 category 的工单”,并将 distinct 工单数作为单独总计。

Files

文件

Under
$RUN/tickets/
:
  • plan.json
    ,
    units.jsonl
    , the planned issues and their per-file units
  • judge/results.json
    ,
    judge/merged.json
    , every judge answer with its attempts and cost, and
    judge/calls/
    with each process's event stream
  • edits.json
    ,
    merges.json
    ,
    merge_edits.json
    ,
    decisions.json
  • final/<ID>.json
    , one posting payload per ticket,
    final/manifest.json
    , and
    postable.json
  • dup_pairs.json
    ,
    bundle/
In the run directory itself, beside
report.md
:
  • tickets.md
    , every ticket as plain markdown behind a perspective by priority table
位于
$RUN/tickets/
下:
  • plan.json
    、
    units.jsonl
    ,包含已规划的问题及其按文件划分的 unit
  • judge/results.json
    、
    judge/merged.json
    ,包含每次 judge 回答及其尝试次数和成本;
    judge/calls/
    包含每个进程的事件流
  • edits.json
    、
    merges.json
    、
    merge_edits.json
    、
    decisions.json
  • final/<ID>.json
    ,每个工单一个发布载荷;还包括
    final/manifest.json
    和
    postable.json
  • dup_pairs.json
    、
    bundle/
在 run 目录本身中、
report.md
旁边:
  • tickets.md
    ,在按视角和优先级排列的表格之后,以纯 Markdown 列出每个工单

Tests

测试

Tests and evals for review-deep and review-tickets, plus the guard tests and preflight tests that cover all four skills, live in
evals/
at the root of this plugin's repository, outside the installed skill.
CheckCommand, from
evals/
Cost
Unit tests, one directory per skill, plus preflight and guard
uv run --with pytest pytest -q unit/review_deep
,
unit/review_tickets
,
unit/preflight
, and
unit/guard
none
End-to-end replay on the harbor fixture, all three kinds
uv run --with pytest pytest -q test_end_to_end.py
none
Live quality eval against
fixture/truth.json
python3 live_eval.py WORK_DIR --run
about $3 at list price
Run the unit tests and the replay after any change to
scripts/
. The replay stops with "prompt changed" when a prompt changes. Record again with
python3 pipeline.py WORK_DIR --mode record
, check the run with
live_eval.py
, and save it with
python3 golden.py save RUN_DIR
. Run the live eval on demand after changing a model, an effort level, or a prompt.
review-deep 和 review-tickets 的测试与评估,以及覆盖全部四个 skill 的 guard 测试和 preflight 测试,都位于此插件仓库根目录的
evals/
中,在已安装 skill 之外。
检查项命令,从
evals/
中执行
成本
单元测试,每个 skill 一个目录,外加 preflight 和 guard
uv run --with pytest pytest -q unit/review_deep
、
unit/review_tickets
、
unit/preflight
和
unit/guard
无
对 harbor fixture 执行三种类型的端到端回放
uv run --with pytest pytest -q test_end_to_end.py
无
  • 针对
    fixture/truth.json
    的实时质量评估 |
    python3 live_eval.py WORK_DIR --run
    | 按标价约 $3 |
修改
scripts/
中的任何内容后,都要运行单元测试和回放。prompt 发生变化时,回放会以“prompt changed”停止。使用
python3 pipeline.py WORK_DIR --mode record
重新录制,使用
live_eval.py
检查该 run,并使用
python3 golden.py save RUN_DIR
保存。修改模型、effort 级别或 prompt 后,可按需运行实时评估。

Rules

规则

  • NEVER post without the operator's explicit go, and never bulk-post before the first ticket has been read back.
  • NEVER let a judge read the live working tree. Judges run in
    run.json
    checkout
    .
  • NEVER accept a model answer without its content check, and never accept an evidence quote that is not the code at the reviewed commit.
  • Keep prompts in
    prompts/
    as
    .txt
    . A markdown formatter rewrote a
    .md
    prompt and changed its meaning.
  • Report counts as measured. A ticket count, a label count, and a finding count are three different numbers.
  • 未经操作者明确同意,绝不发布;在第一个工单完成读回验证前,绝不批量发布。
  • 绝不让 judge 读取实时工作树。judge 在
    run.json
    的
    checkout
    中运行。
  • 绝不在没有内容检查的情况下接受模型回答,也绝不接受与被审阅 commit 处代码不符的证据引文。
  • 将 prompt 保留在
    prompts/
    下并使用
    .txt
    后缀。Markdown formatter 曾重写
    .md
    prompt 并改变其含义。
  • 按实际测得结果报告。工单数、标签数和 finding 数是三个不同的数字。