关于 printing-press-polish
用于发布前检查和打磨 Printing Press 库中生成的 CLI 的技能。它在分叉上下文中运行,并指导版本兼容性检查、差异审查、验证和发布决策。
主要功能
- 01按名称或路径定位 CLI
- 02检查二进制版本兼容性
- 03检测与公共库的差异
- 04运行诊断和修复迭代
- 05应用发布门槛与发布流程
适用场景
- 01验证存在缺口后打磨生成的 CLI
- 02发布前审查库中的 CLI
- 03在构建流水线中重试打磨 CLI
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mvanhorn/ cli-printing-press --skill printing-press-polish安装后在 Claude Code 中输入/printing-press-polish确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/pii-polish.mdpublish-turn-boundary.mdtools-polish.md详细介绍
原文在翻译后有更新,译文可能不是最新。
/printing-press-polish
润色生成的 CLI,使其通过验证并准备好发布。
复盘会改进 Printing Press。润色会改进生成的 CLI。此技能在分叉上下文(context: fork)中运行,因此诊断和修复循环不会污染调用方——诊断输出、修复迭代和重新诊断产生的噪声都限制在润色会话中,调用方收到的则是简洁的摘要。
/printing-press-polish redfin
/printing-press-polish redfin-pp-cli
/printing-press-polish "$PRESS_LIBRARY/redfin"
运行时机
在任何 /printing-press 生成之后运行,尤其是在以下情况:
- shipcheck 判定结果为
ship-with-gaps - 验证通过率低于 80%
- 评分卡低于 85
- 你希望 CLI 一次性达到可发布状态
也可以独立运行于 $PRESS_LIBRARY/ 中的任何 CLI。
设置
# min-binary-version: 4.0.0
PRESS_HOME="${PRINTING_PRESS_HOME:-$HOME/printing-press}"
PRESS_LIBRARY="$PRESS_HOME/library"
_pp_check_disk_space() {
_pp_disk_warn_kb="${PRINTING_PRESS_DISK_WARN_KB:-3145728}"
_pp_disk_fail_kb="${PRINTING_PRESS_DISK_FAIL_KB:-524288}"
case "$_pp_disk_warn_kb$_pp_disk_fail_kb" in
""|*[!0-9]*) return 0 ;;
esac
_pp_disk_path="$PRESS_HOME"
while [ ! -e "$_pp_disk_path" ] && [ "$_pp_disk_path" != "/" ]; do
_pp_disk_path="$(dirname "$_pp_disk_path")"
done
_pp_disk_avail_kb="$(df -Pk "$_pp_disk_path" 2>/dev/null | awk 'BEGIN {
if ((getline header) <= 0 || (getline record) <= 0) exit
field_count = split(record, fields)
if (field_count >= 4) print fields[4]
}')"
case "$_pp_disk_avail_kb" in
""|*[!0-9]*) return 0 ;;
esac
if [ "$_pp_disk_avail_kb" -lt "$_pp_disk_fail_kb" ]; then
echo ""
echo "[setup-error] Critically low disk space on the Printing Press workspace volume."
echo "PRESS_DISK_PATH=$_pp_disk_path"
echo "PRESS_DISK_AVAIL_KB=$_pp_disk_avail_kb"
echo "PRESS_DISK_FAIL_KB=$_pp_disk_fail_kb"
echo "Free disk space or set PRINTING_PRESS_HOME to a volume with more room, then re-run this skill."
echo ""
return 1
fi
if [ "$_pp_disk_avail_kb" -lt "$_pp_disk_warn_kb" ]; then
echo ""
echo "[low-disk] Printing Press workspace volume is low on free space."
echo "PRESS_DISK_PATH=$_pp_disk_path"
echo "PRESS_DISK_AVAIL_KB=$_pp_disk_avail_kb"
echo "PRESS_DISK_WARN_KB=$_pp_disk_warn_kb"
echo "This flow may need several GiB for generated files, Go build cache, module downloads, or repository clones."
echo ""
fi
}
_pp_check_disk_space || { return 1 2>/dev/null || exit 1; }
# Mid-pipeline callers may pass printing_press_bin: <abs-path> in the args
# bundle. Prefer it so forked polish runs keep using the parent skill's
# preflight-selected binary instead of re-resolving through PATH.
PRINTING_PRESS_BIN="${PRINTING_PRESS_BIN:-}"
if [ -z "$PRINTING_PRESS_BIN" ] && [ -n "${ARGUMENTS:-}" ]; then
PRINTING_PRESS_BIN="$(printf '%s\n' "$ARGUMENTS" | sed -nE 's/^[[:space:]]*printing_press_bin:[[:space:]]*(.+)$/\1/p' | head -1)"
fi
if [ -z "$PRINTING_PRESS_BIN" ]; then
PRINTING_PRESS_BIN="$(command -v cli-printing-press 2>/dev/null || true)"
fi
if [ -z "$PRINTING_PRESS_BIN" ]; then
echo "cli-printing-press binary not found."
echo "Install with: go install github.com/mvanhorn/cli-printing-press/v4/cmd/cli-printing-press@latest"
return 1 2>/dev/null || exit 1
fi
if ! command -v go >/dev/null 2>&1; then
echo ""
echo "[setup-error] Go toolchain not found."
echo ""
echo "This Printing Press flow runs Go-based build or validation commands."
echo "Install Go 1.26.9 or newer from https://go.dev/dl/, then verify with:"
echo " go version"
echo "Then re-run this skill."
echo ""
return 1 2>/dev/null || exit 1
fi
echo "PRINTING_PRESS_BIN=$PRINTING_PRESS_BIN"
_pp_semver_lt() {
if [ -z "${PP_SEMVER_A:-}" ] || [ -z "${PP_SEMVER_B:-}" ]; then
echo "[setup-error] semver comparison inputs are missing." >&2
return 2
fi
awk -v a="${PP_SEMVER_A:-}" -v b="${PP_SEMVER_B:-}" 'BEGIN {
split(a, x, "."); split(b, y, ".")
for (i = 1; i <= 3; i++) {
if ((x[i] + 0) < (y[i] + 0)) exit 0
if ((x[i] + 0) > (y[i] + 0)) exit 1
}
exit 1
}'
}
_pp_go_version_norm() {
printf '%s\n' "${PP_GO_VERSION_INPUT:-}" | sed -nE 's/.*go([0-9]+)\.([0-9]+)(\.([0-9]+))?.*/\1.\2.\4/p' | sed -E 's/\.$/.0/'
}
_pp_check_go_currency() {
_pp_go_installed="$(PP_GO_VERSION_INPUT="$(go env GOVERSION 2>/dev/null)" _pp_go_version_norm)"
_pp_go_required="$(PP_GO_VERSION_INPUT="$(go version "$PRINTING_PRESS_BIN" 2>/dev/null)" _pp_go_version_norm)"
PP_SEMVER_A="$_pp_go_installed"
PP_SEMVER_B="$_pp_go_required"
if [ -z "$_pp_go_installed" ] || [ -z "$_pp_go_required" ] || ! _pp_semver_lt; then
return 0
fi
echo ""
if [ "${GOTOOLCHAIN:-auto}" = "local" ]; then
echo "[setup-error] Go $_pp_go_required or newer is required by this cli-printing-press binary (installed: $_pp_go_installed)."
echo "GOTOOLCHAIN=local disables automatic toolchain downloads, so later Go quality gates would fail."
echo "Install Go $_pp_go_required or newer from https://go.dev/dl/, or unset GOTOOLCHAIN."
echo ""
return 1
fi
echo "[go-toolchain-old] Go $_pp_go_required or newer is required by this cli-printing-press binary (installed: $_pp_go_installed)."
echo "PRESS_GO_INSTALLED=$_pp_go_installed"
echo "PRESS_GO_REQUIRED=$_pp_go_required"
echo "Default GOTOOLCHAIN behavior may download the required toolchain during Go commands."
echo ""
return 0
}
_pp_check_go_currency || { return 1 2>/dev/null || exit 1; }
设置完成后,记录 PRINTING_PRESS_BIN=<abs-path>,并在此技能的每次 cli-printing-press ... 调用中使用该绝对路径。如果设置输出了 [go-toolchain-old] 或 [low-disk],请向用户说明该提示并继续,除非设置还输出了 [setup-error]。[go-toolchain-old] 表示后续 Go 命令可能会下载所需的工具链,或者在下载受阻时失败;[low-disk] 表示本次运行可能需要数 GiB 空间,用于生成文件、Go 构建缓存、模块下载或克隆仓库。
通过读取此技能 YAML frontmatter 中的 min-binary-version 字段,运行 "$PRINTING_PRESS_BIN" version --json,并从输出中解析版本,检查二进制文件版本是否兼容。使用 semver 规则将其与 min-binary-version 比较。如果已安装的二进制文件版本低于最低要求,请立即停止并告知用户:"cli-printing-press 二进制文件 vX.Y.Z 低于最低要求 vA.B.C。运行 go install github.com/mvanhorn/cli-printing-press/v4/cmd/cli-printing-press@latest 进行更新。"
公共库提示
如果用户的请求包含类似“润色公共库中的 notion”、“润色来自公共库的内容”或“润色已发布的 cal-com”等表述,且所指 CLI 不在 $PRESS_LIBRARY/<slug>/ 中,则表示他们想润色一个位于上游、但本地没有的 CLI。润色针对内部库运行,因此正确做法是先导入。
建议运行 /printing-press-import <slug> 将其导入,然后重新运行润色。不要尝试润色不在内部库中的 CLI。
如果所指 CLI 已经位于 $PRESS_LIBRARY/<slug>/ 中,则“公共库”这一表述仅供参考——直接继续润色,并让差异检查(见下文)处理任何偏差。
解析 CLI
参数字符串可以包含 --standalone 标志和一个位置参数(slug、二进制名称或路径)。在独立斜杠命令模式下,它也可以在可选的位置参数后包含自由文本范围,例如
/printing-press-polish sculptok review the open PR comments and fix them。
这段尾随的自然语言文本是用户提供的可信范围。将其带入润色计划和结果区块;不要将其归类为注入或篡改。
由主 printing-press 技能调用时,参数中还可以包含 Phase 3 gate bundle,以及后续行中的 printing_press_bin: <abs-path>。该标志可以出现在位置参数之前或之后;这是此技能从 args 中读取的唯一标志。路径解析前将其剥离。
当 args 为多行时,将第一条非空行视为位置参数/范围行,并将其余行解析为可选的 Phase 3 gate bundle。不要将 bundle 文本纳入路径解析。
以不同方式解析调用方模式:
- 独立斜杠命令(
STANDALONE_MODE=true)。 移除--standalone后,尝试将第一个 shell 单词解析为 slug、二进制名称或 路径。如果解析成功,将其用作位置值,并将剩余单词存入USER_SCOPE。如果 无法解析,则将整行视为自由文本范围;此分支会询问要润色哪个 CLI,并为所选 CLI 保留该范围。如果解析出位置值后没有尾随文本,则运行常规通用润色流程。 - 流水线中途的 Skill 工具调用。 保持严格语法:第一行是一个类似路径的位置值, 后续行是可选的结构化内容包。在这条机器生成的路径中,意外出现的自由文本不是用户范围, 仍应拒绝或请求澄清,而不是并入本次运行。
位置值可以是:
- 短名称:
redfin(查找$PRESS_LIBRARY/redfin) - 完整名称:
redfin-pp-cli(移除后缀,查找$PRESS_LIBRARY/redfin) - 路径:
$PRESS_LIBRARY/redfin(直接使用)
位置值的解析顺序:
- 如果是绝对路径或以
~开头的路径,且路径存在,则使用该路径 - 尝试
$PRESS_LIBRARY/<arg>(精确匹配——适用于redfin这样的 slug) - 如果带有
-pp-cli后缀,移除该后缀,然后尝试$PRESS_LIBRARY/<slug>(例如,redfin-pp-cli→redfin) - 模糊搜索:
ls $PRESS_LIBRARY/ | grep -i <arg>,查找相近匹配项
调用方场景与 --standalone 标志。 Polish 有两种调用方;它们通过不同机制调用,并且此技能末尾的「发布提议」仅在 STANDALONE_MODE 为 true 时触发。应根据调用方模式和标志确定 STANDALONE_MODE,而不是根据解析出的路径确定。
- 独立模式(用户调用,
/printing-press-polish redfin)。 通过斜杠命令调用。始终视为STANDALONE_MODE=true——斜杠命令形式就是表明发布意图的入口,即使用户省略标志也是如此。参数是 slug 或二进制名称;解析后指向$PRESS_LIBRARY/<slug>/。这是已发布的副本,也是正确的目标。 - 流水线中途(主 printing-press 技能的第 5.5 阶段,保留路径「润色后重试」)。 通过 Skill 工具调用,参数为
args: "$CLI_WORK_DIR"。参数是一个绝对路径,指向~/printing-press/.runstate/.../runs/.../working/<api>-pp-cli/;解析时必须命中规则 1。默认STANDALONE_MODE=false——在此路径上,发布流程由主 SKILL 负责,因此 polish 不会介入。不要将参数改述为 slug——第 5.5 阶段在工作中的 CLI 晋升之前触发,因此$PRESS_LIBRARY/<slug>/要么不存在,要么保存着上一次运行留下的过期 CLI。 - Skill 工具独立模式覆盖。 非斜杠调用方若确实希望 polish 发布,必须在
args中显式加入--standalone(例如,args: "--standalone $PRESS_LIBRARY/redfin")。没有该标志时,polish 永远不会在 Skill 工具调用中发布——即使解析出的路径恰好位于$PRESS_LIBRARY/下也是如此。标志才是约定;路径不是。
此基于调用方模式的门控机制取代了旧的路径子字符串启发式规则(*.runstate/*)。当主 SKILL 的第 5.5/5.6 阶段顺序颠倒,或从非 .runstate 的临时目录布局调用 polish 时,该启发式规则就会失效:polish 会看到 $PRESS_LIBRARY/<slug>/ 路径,便判断为「独立模式」,然后在流水线中途运行时触发「发布提议」(fork、全局 git 配置、公开 PR)。标志明确无歧义,而默认不发布更安全。
Phase 3 门禁信息包
流水线中途的调用方会在 args 中的 CLI 路径后传入这些字段:
phase3_transcendence_rows_planned: <planned>
phase3_transcendence_rows_built: <built>
phase3_transcendence_rows_missing:
- <manifest row name or command>
prior_sub60_reprint: <true|false>
partial_transcendence_override: <none or build-log note path>
在诊断前解析信息包,并保留这些值供发布逻辑使用。缺少信息包字段表示“没有强制执行 Phase 3 暂停”;不会阻止独立润色。如果 prior_sub60_reprint: true,phase3_transcendence_rows_missing 包含任意行,且 partial_transcendence_override 为空或为 none,则即使本地诊断没有其他问题,润色也必须输出 ship_recommendation: hold。将缺失的行添加到 remaining_issues,以便父级技能显示阻止晋级的具体门禁。
下一个代码块中的锁状态检查是流水线中途场景的安全保障:如果此 CLI 持有构建锁(无论使用哪种名称形式),润色都会拒绝运行。cli-printing-press lock 会在内部规范化 slug ↔ 二进制名称,因此无论 basename 采用哪种形式,此检查都有效。
如果没有匹配项或有多个匹配项,请通过 AskUserQuestion 提示用户。最多显示 4 个匹配项,按修改时间排序(最新的在前),并使用易于理解的相对时间戳(例如“2 小时前生成”)。
CLI_DIR="<resolved path>"
CLI_NAME="$(basename "$CLI_DIR")"
STANDALONE_MODE="<true|false>" # true iff slash-command invocation or --standalone in args; default false for Skill-tool invocations
# Check if there's an active build lock — polish edits would be overwritten
# when the running build promotes to library.
_lock_json=$("$PRINTING_PRESS_BIN" lock status --cli "$CLI_NAME" --json 2>/dev/null)
if echo "$_lock_json" | grep -q '"held".*true'; then
if echo "$_lock_json" | grep -q '"stale".*true'; then
echo "Warning: stale lock exists for $CLI_NAME (build may have crashed)."
echo "Proceeding with polish. Run '$PRINTING_PRESS_BIN lock release --cli $CLI_NAME' to clear."
else
echo "An active build is in progress for $CLI_NAME."
echo "Polish edits would be overwritten when the build promotes."
echo "Wait for the build to finish, then run polish."
exit 1
fi
fi
# Verify it's a valid Go CLI
if [ ! -f "$CLI_DIR/go.mod" ]; then
echo "Not a valid CLI directory: $CLI_DIR"
exit 1
fi
echo "Polishing: $CLI_NAME"
echo "Location: $CLI_DIR"
查找规范和研究目录
API_SLUG="${CLI_NAME%-pp-cli}"
SPEC_PATH=""
for f in "$PRESS_HOME/manuscripts/$API_SLUG"/*/research/*.yaml "$PRESS_HOME/manuscripts/$API_SLUG"/*/research/*.json "$PRESS_HOME/manuscripts/$CLI_NAME"/*/research/*.yaml "$PRESS_HOME/manuscripts/$CLI_NAME"/*/research/*.json; do
if [ -f "$f" ]; then
SPEC_PATH="$f"
break
fi
done
# Build the spec flag once. Empty when no spec was found — diagnostic
# commands accept a missing --spec and degrade gracefully.
SPEC_FLAG=""
if [ -n "$SPEC_PATH" ]; then
SPEC_FLAG="--spec $SPEC_PATH"
fi
# Locate the research dir. dogfood's --research-dir triggers
# checkNovelFeatures, which writes novel_features_built back into
# research.json AND syncs the verified list into .printing-press.json.
# Without this flag, legacy CLIs whose manifest predates the
# novel_features schema fail publish-validate's transcendence gate.
#
# Two layouts to handle, keyed on $CLI_DIR path structure (NOT on the
# absence of a manuscripts entry — re-generating a previously-published
# API leaves stale manuscript entries from prior runs that would point
# scorecard at the wrong research.json):
# 1. Mid-pipeline polish (invoked from the main printing-press flow
# before promote): $CLI_DIR is under $PRESS_RUNSTATE/.../runs/<id>/working/<cli>
# (i.e. the path contains `.runstate/`), and research.json lives at
# $PRESS_RUNSTATE/.../runs/<id>/research.json — $CLI_DIR's grandparent.
# 2. Post-promote (standalone polish): research.json lives at
# manuscripts/<api>/<run-id>/research.json.
RESEARCH_DIR=""
MANIFEST_RUN_ID=""
if [ -f "$CLI_DIR/.printing-press.json" ]; then
if command -v jq >/dev/null 2>&1; then
MANIFEST_RUN_ID="$(jq -r '.run_id // empty' "$CLI_DIR/.printing-press.json" 2>/dev/null || true)"
fi
if [ -z "$MANIFEST_RUN_ID" ]; then
MANIFEST_RUN_ID="$(sed -nE 's/.*"run_id"[[:space:]]*:[[:space:]]*"([^"]+)".*/\1/p' "$CLI_DIR/.printing-press.json" | head -1)"
fi
fi
case "$CLI_DIR" in
*.runstate/*)
_grandparent="$(dirname "$(dirname "$CLI_DIR")")"
if [ -f "$_grandparent/research.json" ]; then
RESEARCH_DIR="$_grandparent"
fi
;;
*)
if [ -n "$MANIFEST_RUN_ID" ]; then
for base in "$PRESS_HOME/manuscripts/$API_SLUG" "$PRESS_HOME/manuscripts/$CLI_NAME"; do
if [ -f "$base/$MANIFEST_RUN_ID/research.json" ]; then
RESEARCH_DIR="$base/$MANIFEST_RUN_ID"
break
fi
done
fi
# Match publish package's fallback: API slug first, then CLI name, each
# using the lexicographically latest run id when the manifest has none.
if [ -z "$RESEARCH_DIR" ]; then
for base in "$PRESS_HOME/manuscripts/$API_SLUG" "$PRESS_HOME/manuscripts/$CLI_NAME"; do
if [ -d "$base" ]; then
_latest="$(find "$base" -mindepth 2 -maxdepth 2 -name research.json -type f 2>/dev/null | sort | tail -1)"
if [ -n "$_latest" ]; then
RESEARCH_DIR="$(dirname "$_latest")"
break
fi
fi
done
fi
;;
esac
# Use a bash array so the flag survives paths with spaces (e.g. when
# $HOME or $PRESS_RUNSTATE resolves through a path containing spaces).
RESEARCH_ARGS=()
if [ -n "$RESEARCH_DIR" ]; then
RESEARCH_ARGS=(--research-dir "$RESEARCH_DIR")
fi
# pii-audit runs against the CLI dir, but publish package later copies the
# same run archive under .manuscripts/<run-id> before enforcing the PII gate.
# Pass the run dir here so polish sees the narrative manuscript files with
# the same relative paths publish will scan.
PII_ARGS=()
if [ -n "$RESEARCH_DIR" ]; then
PII_ARGS=(--manuscripts-dir "$RESEARCH_DIR")
fi
差异检查
在阶段 1 之前,先停止并执行此步骤。不要跳过。完成检查并解决任何差异之前,不要继续执行诊断。
如果有人在此 CLI 上次发布后直接编辑了公共仓库,$CLI_DIR 中的内部副本可能会与公共库(mvanhorn/printing-press-library)中的副本不一致。若对过时的内部副本进行润色,之后再重新发布,就会悄无声息地覆盖仅存在于公共仓库中的修复——这是已发布的 CLI 确实会遇到的问题。
你必须:
-
定位公共库克隆。 如果设置了
$PRINTING_PRESS_LIBRARY_PUBLIC,则使用它;否则,按适合此平台的方式扫描用户的文件系统。通过检查 git remote 是否指向mvanhorn/printing-press-library来验证每个候选项——其他目录可能名称相同(例如 fork 或意外重名)。如果存在多个有效克隆,优先选择最近修改的;只有仍无法确定时才询问用户。 -
在克隆中定位此 CLI。 使用
find <clone>/library -type d -name "<api>-pp-cli"或等效方法。 -
运行
diff -r <public-cli-dir> $CLI_DIR,并使用以下排除项;这些内容在发布后预期会有所不同:.printing-press-tools-polish.json(本地记录文件,不会发布).printing-press-pii-polish.json(本地记录文件,不会发布)go.mod和go.sum——发布时会将模块路径从<api>-pp-cli重写为github.com/mvanhorn/printing-press-library/library/<category>/<api>- 所有仅因导入路径重写而不同的
.go文件(发布步骤会将新的模块路径应用到所有内部导入中)。检查.go文件差异时,扫描实质性更改——除模块路径前缀替换之外的任何更改都属于真实差异。
具体而言:
diff -r --exclude=go.mod --exclude=go.sum --exclude=.printing-press-tools-polish.json --exclude=.printing-press-pii-polish.json <public-cli-dir> $CLI_DIR。不要传入
--exclude='<api>-pp-cli'或--exclude='<api>-pp-mcp'——这些名称同时匹配根目录中的二进制文件以及cmd/<api>-pp-cli/和cmd/<api>-pp-mcp/源码目录。按二进制文件名排除会悄无声息地跳过整个cmd/子树,隐藏main.go中的真实差异。对于已构建的二进制文件,Only in $CLI_DIR: <api>-pp-cli是预期输出的一行,不值得为了过滤它而牺牲完整性。 -
继续之前,先展示检查结果。
结果:
- 未找到克隆 → 用户本地没有公共库。明确说明这一点(“本地未找到公共库;将以内部分副本为准继续”),然后继续。
- 找到克隆,但其中不包含此 CLI → 此 CLI 从未发布,或名称不同。说明这一点,然后继续。
- 已找到且差异为空 → 两者同步。说明这一点,然后继续。
- 已找到但存在差异 → 停止。此时不要运行阶段 1 诊断。向用户列出存在差异的文件。通过 AskUserQuestion 询问:将公共副本同步到内部副本,还是不同步并继续。如果用户选择同步,则将公共副本中存在差异的文件复制到内部副本,然后继续在已同步的内部副本上润色。
显示同步提示之前,检查内部副本中是否有 .printing-press.json 时间戳之后修改的文件(这表示用户在本地进行了尚未发布的润色)。如果有,必须在提示中明确提醒:同步会覆盖尚未发布的本地工作。由用户决定保留本地更改还是拉取公共副本。
同步后(或用户明确选择跳过同步后),其余润色工作均以内部分副本 $CLI_DIR 为准。最终的 /printing-press-publish 步骤会将内部副本推送回公共仓库;无需在那里再次检查差异。
只有在回复中明确说明了上述四种结果之一,才算已执行检查。未说明即视为未执行。
阶段 1:基线诊断
cd "$CLI_DIR"
# Build
go build -o "$CLI_NAME" ./cmd/"$CLI_NAME" 2>&1
# Diagnostics. SPEC_FLAG and RESEARCH_ARGS are set in the "Find spec
# and research dir" step above. RESEARCH_ARGS enables dogfood to
# verify novel features and sync them into .printing-press.json
# (required for publish-validate's transcendence gate).
"$PRINTING_PRESS_BIN" dogfood --dir "$CLI_DIR" $SPEC_FLAG "${RESEARCH_ARGS[@]}" 2>&1
"$PRINTING_PRESS_BIN" verify --dir "$CLI_DIR" $SPEC_FLAG --json 2>&1
"$PRINTING_PRESS_BIN" workflow-verify --dir "$CLI_DIR" --json > /tmp/polish-workflow-verify.json 2>&1 || true
"$PRINTING_PRESS_BIN" verify-skill --dir "$CLI_DIR" --json > /tmp/polish-verify-skill.json 2>&1 || true
# publish-validate is a publish-readiness gate, not a CLI-readiness gate.
# Mid-pipeline polish runs before the main SKILL's promote step and before
# the publish skill packages tools-manifest.json, so its prerequisites
# (manifest.printer from git config github.user, packaged tools manifest,
# phase5 acceptance proof relocated under $CLI_DIR/.manuscripts/<run>/proofs/)
# are not yet satisfied. Running publish-validate here would cascade
# parent-pipeline-owned failures into the polish ship_recommendation,
# which the main SKILL's Phase 5.5 verdict-override then turns into a
# CLI-level hold. Only run publish-validate when polish is the publish
# entry point (slash-command invocation or explicit --standalone).
if [ "$STANDALONE_MODE" = "true" ]; then
"$PRINTING_PRESS_BIN" publish validate --dir "$CLI_DIR" --json > /tmp/polish-publish-validate.json 2>&1 || true
fi
# --live-check samples novel-feature outputs and populates
# live_check.features[].warnings (Wave B entity detection) — required for
# the "Output entity warnings" row below to have data to read.
# RESEARCH_ARGS points scorecard at the run's research.json when the
# CLI lives under $PRESS_RUNSTATE/runs/<id>/working/<cli> (mid-pipeline
# polish). Without it, scorecard looks adjacent to the binary, doesn't
# find research.json, and reports `unable: true`.
"$PRINTING_PRESS_BIN" scorecard --dir "$CLI_DIR" $SPEC_FLAG "${RESEARCH_ARGS[@]}" --live-check --json > /tmp/polish-scorecard.json 2>&1 || true
"$PRINTING_PRESS_BIN" scorecard --dir "$CLI_DIR" $SPEC_FLAG 2>&1
"$PRINTING_PRESS_BIN" tools-audit "$CLI_DIR" --json > /tmp/polish-tools-audit-before.json 2>&1 || true
"$PRINTING_PRESS_BIN" pii-audit "$CLI_DIR" "${PII_ARGS[@]}" --json > /tmp/polish-pii-audit-before.json 2>&1 || true
go vet ./... 2>&1
if command -v gosec >/dev/null 2>&1; then
gosec -fmt=json -out=/tmp/polish-gosec-before.json ./... 2>&1 || true
else
go run github.com/securego/gosec/v2/cmd/[email protected] -fmt=json -out=/tmp/polish-gosec-before.json ./... 2>&1 || true
fi
verify-skill 和 workflow-verify 会与 dogfood/verify/scorecard 并行运行,让 polish 捕获与公共库 CI 相同类型的故障。仅当 STANDALONE_MODE=true 时才运行 publish-validate(通过斜杠命令或 --standalone Skill-tool 调用)。对于独立模式下的 polish,publish-validate 是硬性发布门槛:在该模式下,只要 "$PRINTING_PRESS_BIN" publish validate 报告 passed: false,polish 就不能建议 ship 或 ship-with-gaps。流水线中段的 polish(STANDALONE_MODE=false)会完全跳过 publish-validate——其前置条件(来自 git config github.user 的 manifest.printer、打包好的 tools-manifest.json,以及已迁移到 $CLI_DIR/.manuscripts/<run>/proofs/ 下的 Phase 5 验收证明)由父级流水线负责,此时尚未满足;主 SKILL 的 Phase 6 发布流程会在正确的时机以 publish-validate 作为门槛。请参阅下方的“发布逻辑”,了解这对 ship_recommendation 的影响。
实时矩阵限定条件。 每次运行 scorecard --live-check --json 后,读取 /tmp/polish-scorecard.json,并记录 live_check 是否实际使用了实时样本。只有当 live_check.unable 为 false 且至少评估了一个功能(passed + failed > 0,或等效的功能状态)时,才将其视为 exercised。如果 live_check.unable: true、没有 live_check、没有已评估的功能,或缺少凭据/令牌,则视为 not_exercised。干净的模拟 dogfood/verify 运行仍然有用,但不算通过实时矩阵。
对于手写的 Go 代码,gosec 作为现成的安全静态分析环节运行。若已安装 gosec 二进制文件,优先使用;否则使用固定版本的 go run github.com/securego/gosec/v2/cmd/[email protected] 作为后备方案,这样干净的机器无需单独设置步骤也能获得可复现的检查。读取 /tmp/polish-gosec-before.json,获取基线发现数量和问题详情。如果命令在写入 JSON 前失败,则将缺失的扫描视为 polish 失败:将其添加到 remaining_issues,设置 ship_recommendation: hold,并附上 stderr 摘要,以便下一次运行能区分网络/工具问题和 CLI 缺陷。优先处理手写文件中的发现:internal/cli/、internal/syncer/ 和 internal/store/ 下,前 20 行中没有 Generated by CLI Printing Press 标头的整个文件,均属于 polish 负责的新功能代码。生成器生成的文件中的发现属于 Printing Press 后续候选项,除非能通过修改规范并重新生成来持久修复;不要仅为消除 gosec 报告而手动编辑生成的文件。
如果 Phase 1 基线显示底层 CLI 需要重新发现——例如 HTML/SSR 提取损坏、捕获稀疏(源手稿中少于 5 个唯一端点)、端点形状错误、缺少 GraphQL 操作哈希,或有任何信号表明 CLI 是根据不完整的捕获生成的——polish 通常不会自行执行浏览器捕获。如需重新发现,请使用运行时已提供的捕获后端(Claude chrome-MCP mcp__claude-in-chrome__* 和 computer-use mcp__computer-use__*),而不是另行发明捕获流程。polish 执行重新发现并不常见,但确实可能发生。
将发现的问题分类:
| 类别 | 来源 | 检查内容 |
|---|---|---|
| 验证失败 | verify --json | 得分 < 3 的命令 |
| SKILL 静态检查失败 | verify-skill --json | 任何 findings[] 中 severity=error 的条目(flag-names、flag-commands、positional-args、unknown-command、canonical-sections)。硬性发布门槛:存在这些问题时,不得触发 ship。 |
| 工作流缺口 | workflow-verify --json | 判定结果为 workflow-fail。软性门槛:在 remaining_issues 中列出;如果工作流是 CLI 的主要价值,则将状态降级为 hold。 |
| 发布验证失败 | publish validate --json | passed: false。仅限独立模式下的润色(只有在 STANDALONE_MODE=true 时运行);在发布前置条件尚未满足的流水线中段润色期间会跳过。运行时,这是硬性发布门槛:publish validate 失败时,不得触发 ship。如果唯一失败的检查是缺少 phase5 验收,则报告 phase5 acceptance required,并提供下一步命令:先进行身份验证,然后运行 "$PRINTING_PRESS_BIN" dogfood --dir "$CLI_DIR" $SPEC_FLAG --live --level quick --write-acceptance <proofs-dir>/phase5-acceptance.json。如果验证错误中包含证明目录,请使用该目录。 |
| 安全静态分析失败 | gosec JSON | 任何 Issues[] 条目,尤其是 G201/G202 SQL 构造、G101 凭据字面量,或不安全的文件/命令执行。如果问题出现在手写的新功能 Go 代码中,则属于硬性发布门槛。 |
| 死代码 | dogfood | 未使用的函数、未使用的标志 |
| 过时文件 | dogfood | 未注册的命令 |
| 描述问题 | dogfood | 根命令 Short 为样板文本 |
| README 缺口 | scorecard | README 得分 < 8 |
| 示例缺口 | dogfood | 缺少示例的命令 |
| Go vet 问题 | go vet | 任何输出 |
| 输出实体警告 | scorecard JSON | live_check.features[].warnings — 面向用户的输出中包含原始 HTML 实体 |
| 输出合理性 | Phase 4.85 | Agent 输出审查发现的问题 |
| MCP 工具质量 | tools-audit | Short 为空、Short 内容单薄、缺少只读注释、MCP 描述内容单薄 |
| 客户 PII | pii-audit | 高风险文件(手稿、fixtures、README)中出现卡号后 4 位、电子邮件、电话号码、ZIP+4、邮政地址格式 |
环境问题与 CLI 缺陷。 Phase 1 的某些输出会报告并非真正 CLI 错误的失败,不应阻止发布:
scorecard --live-check报告SQLITE_BUSY、网络超时、来自模拟对象或过期令牌的401,或取决于测试工作区权限/状态的 HTTP 错误——这些是测试环境问题,而非 CLI 缺陷。verify模拟测试框架在包含二进制输出的命令上出现不稳定问题(例如,qr返回的 PNG 无法由子字符串匹配器验证),或在带有可选位置参数的命令上出现问题,因为试运行输出中本就可能不包含 verify 探测字符串。- Learn-loop 命令:dogfood/verify 矩阵现已覆盖默认启用的 learn 功能面(
teach、recall、learnings、playbook)。teach和teach-playbook在不带参数调用时会有意以状态码 2 退出,并通过pp:typed-exit-codes声明,因此verify会将其评为通过,而dogfood --live会将happy_path和json_fidelity检查记录为跳过,原因是declared non-zero exit 2;这既不是缺陷,也不应作为“修复”退出码的理由。跳过 happy path 不计入 phase5 实时覆盖率,因此,如果某个新功能在其 happy path 中始终以非零状态码退出,则会被报告为未覆盖,而非已覆盖。全新打印中的learnings stats合理地会报告零值和空内容;这表示本地存储为空,并非缺陷。
请在 skipped_findings 中将这些归类为环境问题,并注明具体原因;不要在 Phase 2 中花时间尝试“修复”它们。润色技能的发布逻辑已将实时检查失败排除在门槛之外,但 Agent 仍应注明这些问题,以便审查者了解它们已被考虑并有意排除。
第 4.85 阶段 — Agent 输出审查(B 波)
上述机械诊断完成后,通过 Skill 工具调用 printing-press-output-review 子技能。该子技能采用 context: fork,并负责分发提示词、门控逻辑和已知盲点,是主 printing-press 技能共享的唯一事实来源。
Skill(
skill: "cli-printing-press:printing-press-output-review",
args: "$CLI_DIR"
)
解析返回的 ---OUTPUT-REVIEW-RESULT--- 块。status: WARN 的发现归入上述诊断类别,以便第 2 阶段的修复同时解决基于规则和合理性方面的问题。status: SKIP 仅供参考——记录下来,但不要阻止流程。
适用 B 波门控:所有发现都只是警告,绝不构成阻断项。明显且修复成本低的问题应予修复;若暂缓处理,则添加简短注释说明。
记录基线评分:评分卡总分、验证通过率、试用判定、实时矩阵限定词(exercised / not_exercised)、go vet 问题数、gosec 发现数、输出审查发现数。
第 2 阶段:修复
按优先级顺序修复。每完成一个优先级级别后,更新锁心跳:
"$PRINTING_PRESS_BIN" lock update --cli "$CLI_NAME" --phase polish 2>/dev/null
运行时变体默认项检查清单
如果润色修复添加或更改了运行模式、数据源选项、身份验证级别、传输方式或其他面向用户的默认项,请在选定默认项前记录以下简短检查清单:
- 面向用户的默认项: 用户在未使用额外标志或配置时会获得哪种行为。
- 兼容性风险: 现有命令、脚本、MCP 工具或已保存的配置是否会改变行为。
- 验证命令: 用于证明默认项和非默认项退出方式都有效的确切命令。
将检查清单保留在润色备注或结果块中。对于不会更改运行时变体或默认项的常规 Bug 修复,无需填写。
横切 API 调用插桩
如果润色构建的功能类别必须观测每个出站 API 调用,例如配额台账、请求日志或审计跟踪,请在 internal/client/client.go 中对生成的客户端中间件进行插桩,而不要在各个命令处理程序中单独插桩。如果存在共享的分发前钩子,应优先使用;否则,同时覆盖 do() 和 doRead()。do() 路径处理标准端点镜像、同步迭代,以及使用生成客户端的新功能;doRead() 则处理通过类似 POST 的传输方式执行的只读操作,例如 GraphQL 查询、JSON-RPC 读取,以及标记为 mcp:read-only 的基于 POST 的搜索。
按命令设置钩子会导致计数偏低,因为它们只能观测到润色过程中涉及的命令。
新增功能的数据路由
当 polish 新增或修复会读取 API 响应数据并写入本地存储的命令时,应通过生成的类型化架构路由数据,而不是直接将原始响应 JSON 写入表中:
- 阅读待缓存资源对应的
internal/types/<resource>.go和internal/store/<resource>.go。只要这些文件生成了类型化插入/更新辅助函数,就应使用它们。如果生成的资源缺少辅助函数,应先创建辅助函数,再编写任何持久化代码。 - 在确定插入映射正确之前,对照规范架构和真实的响应示例检查响应结构。
- 持久化之前,将 API 响应解码为类型化结构体。除非目标表是手动编写的迁移中声明的 polish 自有自定义表(见下文原始 SQL 例外),否则不要根据非类型化的
map[string]any或原始json.RawMessage构造INSERT INTO ...语句。 - 根据资源类型确认目标表,而不是根据新增命令最初使用的查询来判断。获取了
<child>记录的命令必须插入<child>行,而不是父级行或相邻的便利表。 - 插入前规范化嵌套的响应标识符。如果 API 将标量 id 包装在还包含元数据的对象中,应提取标量 id 字段并存储该值;绝不能将整个 id 对象存为主键或外键引用。
只有对手动编写的迁移中声明的 polish 自有自定义表,才允许使用原始 database/sql 写入。在这种情况下,应在 internal/store/ 中明确声明表架构,说明为何不适用生成的资源辅助函数,并且仍须在持久化前将嵌套标识符解码为标量。
优先级 0:MCP 表面迁移(旧版 CLI)
如果 Phase 1 的 dogfood 报告 MCP Surface: FAIL,且原因是奇偶校验不匹配,那么该 CLI 是在运行时 cobratree 遍历器出现之前生成的,目前仍使用静态的 internal/mcp/tools.go 表面。修复步骤是固定的:
"$PRINTING_PRESS_BIN" mcp-sync "$CLI_DIR"
此操作会将 MCP 表面迁移到运行时遍历器,重新生成 tools-manifest.json 和 internal/mcp/tools.go,并应用所有 mcp-descriptions.json 覆盖项。如果操作因 mcp-sync refused 和 reprint required 退出,请停止本次 polish 流程并交接给 /printing-press-reprint;目标 CLI 的生成客户端对于当前 MCP 处理程序来说太旧了,因此仅重写 tools.go 会导致其构建失败。交接时请说明,重新生成流程必须针对重新生成的 CLI 运行常规 dogfood 门禁,并在发布前确认 MCP Surface: PASS。不要针对过时的 $CLI_DIR 重新运行 dogfood。成功运行 mcp-sync 后,请在此处重新运行 dogfood;奇偶校验门禁应转为 PASS。在已兼容且已使用运行时遍历器的 CLI 上运行 mcp-sync,只会刷新而不会产生变更。
如果 CLI 的 dogfood MCP 门禁已通过,则跳过此优先级。
优先级 1:安全静态分析失败
对于 /tmp/polish-gosec-before.json 中的每条 gosec 发现:
- 阅读引用的文件,并确认它是否为手工编写。若
internal/cli/、internal/syncer/或internal/store/下的整个文件,其前 20 行不包含Generated by CLI Printing Press,则该文件属于 polish 自有的新功能代码。 - 如果发现位于手工编写的代码中,先在源代码中修复根本原因,再处理优先级较低的 polish 项目。例如:用参数化查询替换 SQL 字符串拼接,避免使用不可信参数调用 shell,并将看起来像凭据的字面值移至配置或环境变量处理逻辑中。
- 如果 gosec 标记的是生成代码,不要手动编辑生成文件。应修复上游规范并重新生成,或者添加一条
skipped_findings,将其标记为生成器后续处理候选项,并注明规则 ID 和文件路径。 - 如果 gosec 报告的是误报,应保持抑制范围尽可能小并说明原因。只有在代码确实安全且理由长期有效时,才优先使用局部的
// #nosec G### -- reason;否则应修复代码。
手工编写的新功能 Go 代码中未解决的 gosec 发现属于硬性阻塞项:必须将其列入 remaining_issues,令 ship_recommendation: hold,并在修复可能通过机械方式完成时设置 further_polish_recommended: yes。
优先级 2:验证失败
对于任何 dry-run 或 exec 验证失败的命令:
- 阅读命令文件
- 查找
Args: cobra.ExactArgs(N)或类似约束 - 移除
Args:字段 - 在
RunE开头添加:if len(args) == 0 { return cmd.Help() } - 对于需要 2 个或更多参数的命令,使用
if len(args) < 2 - 检查 dry-run 是否会因数据为 nil 而崩溃,并添加保护:
if flags.dryRun { return nil }
优先级 3:死代码
- 对于 dogfood 标记的每个死函数,搜索所有
.go文件以确认它确实未被使用(而不只是定义本身匹配到) - 如果确实未使用:删除该函数
- 如果被其他辅助函数使用:保留(属于误报)
- 删除函数后,移除未使用的导入
- 删除过时文件(已提升但未在 root.go 中注册的命令)
优先级 4:CLI 描述和元数据
- 阅读
internal/cli/root.go中根命令的Short - 如果包含模板化内容(“Reverse-engineered...”或原始 API 标题),请改写:
模式:
"<Product> CLI with <capability-1>, <capability-2>, and <capability-3>" - 检查命令是否缺少
Example字段。添加包含领域专属值的真实示例。
优先级 5:README
首要规则:README 中列出的每条命令都必须运行 <cli> <cmd> --help。 不要臆测标志名称、参数格式或有效值。如果你写了 --start-time,但标志实际是 --start,那么 README 就是错误的,用户第一次尝试时就会报错。
已渲染部分的事实来源文件
编辑 README.md、SKILL.md 或 .printing-press.json 之前,请先确认该部分是否由源文件渲染生成。Dogfood 和重新生成会覆盖这些已渲染部分,因此直接修改只是暂时的,仅应在检查当前输出时使用。
| 已渲染部分或字段 | 事实来源文件::字段 | 润色工作流 |
|---|---|---|
README ## Unique Features | research.json::novel_features_built[] | 编辑底层 research.json 中的功能描述/示例,然后使用 --research-dir 重新运行 dogfood。 |
SKILL ## Unique Capabilities | research.json::novel_features_built[] | 编辑底层 research.json 中的功能描述/示例,然后使用 --research-dir 重新运行 dogfood。 |
internal/mcp/tools.go command_mirror_capabilities | research.json::novel_features_built[] | Dogfood 会报告磁盘上的区块存在差异,并保持其不变。只有在要从 research.json 替换该区块时,才传入 --overwrite-command-mirror。 |
| README 快速入门 | research.json::narrative.quickstart[] | 编辑 research.json 中的命令/注释,然后重新生成或重新运行 dogfood/渲染步骤。 |
| SKILL 配方 | research.json::narrative.recipes[] | 编辑 research.json 中的配方标题、命令或说明,然后重新生成或重新运行 dogfood/渲染步骤。 |
| README/SKILL 故障排除 | research.json::narrative.troubleshoots[] | 编辑 research.json 中的问题/解决方法,然后重新生成或重新运行 dogfood/渲染步骤。 |
.printing-press.json display_name、description、mcp_* | WriteManifestForGenerate;对于 description/display-name 覆盖项,请编辑规范(info.title、info.x-display-name、info.description) | 编辑规范或重新运行清单写入器。除非是为了临时诊断,否则不要手动编辑生成的清单元数据。 |
对于这些已渲染部分,建议采用以下循环:编辑源字段,使用 --research-dir "$RESEARCH_DIR" 重新运行 dogfood,或按需重新生成 CLI,然后再运行一轮,确认渲染后的 README/SKILL 文本保持不变。如果直接编辑 README.md 或 SKILL.md 中的这些部分,预期下一次 dogfood 同步或重新生成会覆盖修改。
查找手稿源文件:
PRESS_HOME="${PRINTING_PRESS_HOME:-$HOME/printing-press}"
API_SLUG="${CLI_NAME%-pp-cli}"
RESEARCH_JSON=""
for f in "$PRESS_HOME/manuscripts/$CLI_NAME"/*/research.json \
"$PRESS_HOME/manuscripts/$API_SLUG"/*/research.json; do
if [ -f "$f" ]; then RESEARCH_JSON="$f"; break; fi
done
如果 RESEARCH_JSON 存在,且某个已渲染部分的文案、示例或标志引用有误,请先修复该文件中对应的字段。对于新颖功能,dogfood 会验证 research.json::novel_features[],将通过验证的集合写入 research.json::novel_features_built[],并根据该验证集合同步 README ## Unique Features、SKILL ## Unique Capabilities、.printing-press.json novel_features,以及根帮助中的高亮内容。除非传入 --overwrite-command-mirror,否则 internal/mcp/tools.go 中存在差异的 command_mirror_capabilities 区块会保持不变。
必需章节(必须完整且正确)
- 标题:
# <产品名称> CLI——使用产品的真实名称,并确保大小写和标点正确(例如,使用“Cal.com”,而不是“Cal Com”) - 副标题:用一句话描述该 CLI 为用户提供的功能,并与根目录中的
Short字段一致。不要描述 API。 - 安装:正确的安装命令。使用 printing-press-library 仓库 URL,而不是不存在的单个 CLI 仓库 URL。
- 身份验证:说明如何设置
<API>_API_KEY环境变量,以及从哪里获取密钥(链接到提供商的设置页面);如果支持自托管 URL 覆盖,也要说明。阅读config.go,找出所有环境变量。 - 快速入门:提供 3–5 条用户实际会首先运行的命令。选择既最实用(日常会运行),又能展现 CLI 的价值(说明为何要安装它,而不是使用 curl)的命令。通常包括:
doctor→sync→ 超越基础功能的命令(today、health)→search。避免使用原始列表命令——这类命令只会输出数据,无法体现 CLI 存在的意义。 - 命令:按类别整理成表格。按领域功能分组(Scheduling、Analytics、Account、Utilities),而不是按实现结构分组。
- 输出格式:展示
--json、--select、--csv、--compact、--dry-run、--agent。使用真实命令,而不是占位符。 - Agent 用法:说明适用于 Agent 的特性和退出代码。
- 操作指南:提供 8–15 个示例,使用经
--help验证的标志名称。展示 CLI 的独特功能:超越基础功能的命令、筛选器、SQL 查询、管道。至少包含一个修改示例。 - 健康检查:展示实际的
doctor输出,而不是占位符。 - 配置:列出
config.go中的所有环境变量并附上说明。包含配置文件路径。 - 故障排除:将常见错误与退出代码对应,并提供解决方法。
可选章节(酌情添加)
- 速率限制:如果 API 记录了限制
- 自托管:如果 CLI 支持
--api-url或BASE_URL覆盖 - 分页:如果 API 的分页行为值得说明
- 来源与灵感:致谢社区项目(由机器生成;如果存在,请保留)
优先级 5.5:SKILL 静态检查失败(verify-skill)
读取 /tmp/polish-verify-skill.json,查看完整的问题列表。每个问题都包含一个 check(flag-names、flag-commands、positional-args、unknown-command 或 canonical-sections)、一个 command(SKILL 声称的路径)以及一个描述不匹配情况的 detail。常见情况及修复方法如下:
flag-names— SKILL 在<cli> ...调用中引用了--foo,但internal/cli/*.go中没有任何命令声明该标志。要么示例有误(修正 SKILL 或删除该操作说明),要么该标志已被删除(判断是否应该恢复)。不在范围内: 调用其他工具的行中的标志(例如,npx -y @mvanhorn/printing-press install <api> --cli-only、gh pr create --base ...、go install ...)。按操作说明范围执行的 flag-names 检查会按设计忽略这些内容——切勿为了让 verify-skill 以 0 退出而删除外部工具的标志,也切勿用伪造的斜杠命令替换安装说明。如果问题仍然针对外部工具的标志触发,这是 verify-skill 的错误,不是 SKILL 的问题;应报告该问题,而不是编辑 SKILL。flag-commands—--foo已在别处声明,但未在<cmd>上声明。该标志确实存在,但不属于 SKILL 调用的命令。两种修复方法:- 如果该标志是通过
addXxxFlags(cmd, ...)之类的共享辅助函数添加的,请将cmd.Flags().StringVar(...)声明直接内联到受影响命令的源文件中。verify-skill 的 grep 无法跟踪函数调用的间接关系。 - 如果 SKILL 示例确实有误,请将示例改为使用该命令已声明的标志。
- 如果该标志是通过
positional-args—got N positional args; Use: "<cmd> <arg>" expects M-M。SKILL 操作说明传入了 N 个位置参数,但命令的Use:声明要求 M 个参数。两种修复方法:- 如果命令也接受通过
--flag传入值,请将Use: "cmd <arg>"改为Use: "cmd [arg]"(方括号表示可选参数)。对于声明为可选位置参数的命令,verify-skill 会正确接受仅使用--flag的调用。 - 如果 SKILL 示例缺少必需的位置参数,请修正示例。
- 如果命令也接受通过
canonical-sections—install section drift: hand-edit detected in a generator-owned section。## Prerequisites: Install the CLI块已被编辑,与生成器当前针对该 CLI 生成的内容不一致。**不要手动编辑安装部分。**该部分由internal/generator/templates/skill.md.tmpl模板生成,参数为(api_name, category, uses_browser_http_transport);任何偏差都意味着自动化步骤或人员修改了由机器管理的文本。请重新生成已输出的 CLI 来解决(在此目录中运行printing-press regen;对于已发布的 CLI,请从规范重新生成并重新发布)。如果规范文本本身有误(例如确实需要更改安装说明),请修复模板,而不是已输出的 CLI。
编辑 SKILL.md 的其他部分时,请先读取受影响的部分,并在编辑后再次读取。Edit 会替换字面字符串;如果周围的内容已发生偏移,单次 Edit 可能会将第二份内容块拼接到原内容块后面,而不是替换原内容。
修复后,重新运行 "$PRINTING_PRESS_BIN" verify-skill --dir "$CLI_DIR",并确认退出码为 0 后再继续。
优先级 6:剩余的内部试用问题
- 路径有效性不匹配
- 身份验证协议不匹配
- 示例偏差(示例引用了错误的命令)
- 数据流水线完整性问题
优先级 7:MCP 工具质量
你现在的目标是确保此 CLI 暴露的每个 MCP 工具都有符合 Agent 要求的描述,并且读写分类正确。 工具描述和分类决定了 Agent 如何发现工具,以及是否调用工具——描述过于简略和缺少注释会直接降低 Agent 体验,而第 1 阶段的机械检查(verify、dogfood)不会发现这类问题。
请暂停并:
- 运行
"$PRINTING_PRESS_BIN" tools-audit "$CLI_DIR" --json,查看机械检查结果(Short 为空、Short 过于简略,以及名称类似读取操作的命令缺少mcp:read-only)。 - 你必须阅读
references/tools-polish.md,并按照其中的说明处理检查结果,还要对每条命令进行判断审查——无论审计是否标记了该命令。审计只能发现机械性问题;描述质量以及边界分类(只读还是本地写入)始终需要 Agent 进行判断。不得跳过此步骤。 - 接受 MCP 描述问题有更严格的要求。 接受
thin-mcp-description和empty-mcp-description问题时,必须为每条问题填写三个决策前字段(spec_source_material、target_description、gap_analysis)。二进制程序会拒绝使用相同理由批量接受超过 5 条问题的操作,并会拒绝任何未解决 MCPDescriptionQuality 问题的“完成”运行。预期做法是通过覆盖或改进生成器来修复;接受问题的情况应当很少。完整要求请参阅references/tools-polish.md中的“Marking a finding accepted”。
只有当审计摘要行显示 no pending findings,且没有 incomplete: 区块时,才能继续到“完成所有修复后”——所有检查项(决策前字段、重复理由、评分卡差异)都必须通过。
优先级 8:客户 PII 检查门槛
你现在的目标是清空 PII 台账,使 promote 和 publish 检查通过。 PII 检查门槛是确定性底线,可防止真实客户信息进入已发布的库内容。它会检查高风险文件中是否存在卡号末 4 位、电子邮件、美国电话号码、ZIP+4 邮编以及邮寄地址等模式。
请暂停并:
- 运行
"$PRINTING_PRESS_BIN" pii-audit "$CLI_DIR" "${PII_ARGS[@]}"查看待处理问题(或者读取第 1 阶段基线文件/tmp/polish-pii-audit-before.json)。当RESEARCH_DIR存在时,审计还会包含该次运行的research.json和research/*.md,并使用.manuscripts/<run-id>/...路径,以便接受的处理结果能延续到publish package。 - 你必须阅读
references/pii-polish.md,并按照其中针对每条问题的决策树操作——在源文件中将真实信息替换为不会匹配的占位符,或者填写决策前字段category和evidence_context后接受该问题。 - 接受 PII 问题有严格要求。 字段缺失、使用相同理由接受 6 条或更多问题,或者不修复源文件就整体接受 ≥10 条问题,都会导致检查失败。完整规则请参阅
references/pii-polish.md中的“The accept contract”和“Forbidden accept patterns”。
只有当 pii-audit 显示 no pending findings,且没有 incomplete: 区块时,才能继续到“完成所有修复后”。
完成所有修复后
go build -o "$CLI_NAME" ./cmd/"$CLI_NAME"
gofmt -w .
阶段 3:重新诊断
在修复后的 CLI 上重新运行诊断检查:
# RESEARCH_ARGS must travel with dogfood here too — without it,
# checkNovelFeatures doesn't re-sync novel_features_built after Phase 2
# edits, and publish-validate's transcendence gate reads stale state
# from Phase 1's pass.
"$PRINTING_PRESS_BIN" dogfood --dir "$CLI_DIR" $SPEC_FLAG "${RESEARCH_ARGS[@]}" 2>&1
"$PRINTING_PRESS_BIN" verify --dir "$CLI_DIR" $SPEC_FLAG --json 2>&1
"$PRINTING_PRESS_BIN" workflow-verify --dir "$CLI_DIR" --json 2>&1
"$PRINTING_PRESS_BIN" verify-skill --dir "$CLI_DIR" --json 2>&1
if [ "$STANDALONE_MODE" = "true" ]; then
"$PRINTING_PRESS_BIN" publish validate --dir "$CLI_DIR" --json 2>&1
fi
"$PRINTING_PRESS_BIN" scorecard --dir "$CLI_DIR" $SPEC_FLAG 2>&1
"$PRINTING_PRESS_BIN" tools-audit "$CLI_DIR" 2>&1
"$PRINTING_PRESS_BIN" pii-audit "$CLI_DIR" "${PII_ARGS[@]}" 2>&1
go vet ./... 2>&1
if command -v gosec >/dev/null 2>&1; then
gosec -fmt=json -out=/tmp/polish-gosec-after.json ./... 2>&1 || true
else
go run github.com/securego/gosec/v2/cmd/[email protected] -fmt=json -out=/tmp/polish-gosec-after.json ./... 2>&1 || true
fi
记录修复后的评分,包括最终 scorecard --live-check --json 输出中的实时矩阵限定条件。如果 gosec 命令在写入 /tmp/polish-gosec-after.json 前失败,则将缺少修复后扫描视为润色失败:将其添加到 remaining_issues,设置 ship_recommendation: hold,并附上 stderr 摘要。如果 verify-skill 仍有任何 severity=error 发现,workflow-verify 仍报告 workflow-fail,publish-validate 仍报告 passed: false(仅限独立模式——流水线中途的润色不会运行此检查),gosec 仍报告手写新功能 Go 代码中存在未解决的发现,pii-audit 仍有待处理的发现或门禁失败,或者最终实时矩阵限定条件为 not_exercised,则不能触发发布(见下方发布逻辑)。对于未执行的实时矩阵,添加类似以下内容的 remaining_issues 条目:live matrix not exercised (mock-only/no live token); run the live gate before publish。
发布逻辑
计算发布建议:
-
ship:verify >= 80%,scorecard >= 75,没有严重故障,且 verify-skill 退出码为 0(没有 SKILL/CLI 不匹配),且 workflow-verify 不是workflow-fail,且(当STANDALONE_MODE=true时)publish-validate 报告passed: true,且 gosec 在手写新功能 Go 代码中没有未解决的发现,且 tools-audit 没有待处理的发现(每项发现都已修复,或已明确接受并说明理由),且 pii-audit 没有待处理的发现和门禁失败(每项 PII 发现都已在源代码中修复,或已通过有效的预决策字段接受)。SKILL/workflow/publish/gosec/PII 门禁都是硬性要求:如果 CLI 随附的 SKILL 对其功能描述不实(verify-skill 发现),Agent 就会收到错误指引;如果 CLI 的主要工作流未通过验证,就不能算真正发布;如果 publish-validate 拒绝该 CLI,它就不具备发布条件;如果手写新功能代码仍存在未解决的安全静态分析发现,就会成为审查时的攻击目标;如果 CLI 未通过 promote/publish 阶段的 pii-audit,它最终也会阻碍发布。publish-validate 门禁仅在润色流程运行了该检查时适用(独立模式);流水线中途的润色会将发布就绪检查留给主 SKILL 的阶段 6。 -
ship-with-gaps:verify >= 65%,scorecard >= 65,仍有非严重缺陷,且上述 SKILL/workflow/gosec/PII 门禁均已满足,且(当STANDALONE_MODE=true时)publish-validate 门禁已满足,且 README 中有一个## Known Gaps区块,列出面向用户的缺陷。仅适用于重构或外部依赖阻碍彻底修复的少数情况。使用
ship-with-gaps时,README 中必须包含 Known Gaps。 下游用户看到的是已发布的库副本;如果结论声称存在缺陷,但 README 却将其隐藏,下游用户就会在没有任何说明的情况下遇到行为异常的 CLI。在给出ship_recommendation: ship-with-gaps之前:-
阅读 CLI 的
README.md。如果已存在## Known Gaps章节(例如主 SKILL 阶段 4 在润色开始前已写入),确认其中涵盖remaining_issues中面向用户的条目。为润色过程中发现的任何新用户可见缺陷添加项目符号。 -
如果缺少
## Known Gaps,则添加该章节,放在## Quick Start之后(或## Usage之前),以符合## Unique Features的位置惯例。remaining_issues中每项面向用户的内容都单独列为一条。请从用户的角度描述:哪个命令行为异常,以及可用什么方法绕过。示例:## Known Gaps - **`analytics export --csv`** 在事件数超过 10k 的工作区中会返回被截断的行。在底层导出端点实现分页之前,请使用 `--json` 并通过管道传给 `jq` 作为替代方法。 -
填充该部分时,筛选
remaining_issues,只保留面向用户的条目。内部事项(例如验证已弃用标志是否存在偏差、调整 MCP 描述、润色内部备注)不属于公开的“已知问题”。如果 Agent 无法从remaining_issues中识别出任何面向用户的问题,结论应为ship,而不是ship-with-gaps。 -
在
fixes_applied中列出每项“已知问题”的写入或更新,以便调用方告知用户这项操作已经完成。
如果润色流程无法根据现有证据负责任地填写“已知问题”(例如,
remaining_issues全是内部术语,无法面向用户解读),则应将结论降级为hold,而不是不作说明就发布。 -
-
hold:验证得分 < 65 或评分卡 < 65,或存在严重失败,或 verify-skill 仍有未解决的问题,或 workflow-verify 报告workflow-fail,且该工作流是 CLI 的主要价值,或(当STANDALONE_MODE=true时)publish-validate 报告passed: false,或 gosec 在手写的新功能 Go 代码中仍报告未解决的问题,或 pii-audit 仍有待处理的问题或门禁失败,或 Phase 3 门禁组合指出这是一次先前得分低于 60 的重印,缺少超越性条目,且没有获批的partial_transcendence_override。中间流程中的润色不会因 publish-validate 而进入hold,因为该模式下不会运行这项检查,并且publish_validate_*会标记为skipped (mid-pipeline)。
更进一步,但不要弄虚作假
发布门槛是底线,而非上限。通过门槛后,请检查仍未达到满分的评分卡维度,并判断每项差距是真实问题还是结构性因素:
- 找到根本缺陷,而不是盯着分数。 评分卡是质量的衡量指标,而不是目标本身。README 得分为 8/10,可能是缺少 Cookbook 部分或命令已过时——这是实际存在且可以修复的问题。
mcp_surface_strategy在拥有 200 个端点的 API 上得分为 2/10,可能是在指出其接口大多只是端点镜像——这也可能可以改进。 - 如果有真正有价值的 Agent 级改进,就着手完成。 改进描述、补充缺失的标志说明、完善薄弱的 README 部分,或添加能反映实际用法的示例。CLI 会变得更好,分数也会随之提高。
- 如果是结构性缺陷,就记录并接受。 某些维度假设 CLI 所属领域具备它并不具备的能力(例如,用写入工作流维度评估只读 API,用认证维度评估没有认证机制的 CLI,或用针对大型 API 校准的
surface_strategy门槛惩罚小型 API)。在skipped_findings中注明原因,然后继续。 - 绝不要为了满足评分器而添加脚手架。 虚构命令、测试、标志,或纯粹为了提高分数而写的模板化文字,都会损害 CLI,只为迎合代理指标。评分器的设计本就不完美(AGENTS.md 中“评分可能不准确”的说明适用)。相信实际判断,而不是数字。
MCP 评分卡维度对应的是规范字段,而非生成器代码
当 mcp_token_efficiency、mcp_tool_design、mcp_remote_transport 或 mcp_surface_strategy 未达到满分时,修复方式几乎总是编辑规范并重新生成(或从刚生成的目录树运行 regen-merge),而不是修改生成器模板。润色可以解决这些问题——不要将其归类为“向生成器管理的文件添加功能,适合回溯”。Cobratree 的 shell 外调工具已从 Short(而非操作员 Long 帮助)生成目录,因此遗留的 mcp_token_efficiency 压力来自类型化端点描述,而非框架 --help。
| 弱项维度 | 修复它的规范字段 | spec.yaml 的 mcp: 块中要添加的内容 |
|---|---|---|
mcp_remote_transport | mcp.transport | transport: [stdio, http](端点数不超过 spec.DefaultRemoteTransportEndpointThreshold 的小型 API 默认已启用此项;仅当规范选择了更窄的列表,或 API 超过阈值但仍需要远程访问时,才需要覆盖) |
mcp_token_efficiency、mcp_surface_strategy | mcp.endpoint_tools、mcp.orchestration | endpoint_tools: hidden + orchestration: code(Cloudflare 模式:将约 70 个原始端点工具精简为 <api>_search + <api>_execute;所有端点仍可通过 execute 访问) |
mcp_tool_design | mcp.intents | 为 API 支持的工作流定义多步骤意图组合 |
mcp_description_quality | mcp-descriptions.json(CLI 根目录中的覆盖文件) | 按工具设置描述覆盖项;为单薄的规范派生描述补充更丰富的文本,无需编辑规范 |
建议阈值:当类型化端点数大于 50 时,默认建议启用全部四项(transport、endpoint_tools=hidden、orchestration=code,以及适用于主要工作流的 intents)。小型 API(<= spec.DefaultRemoteTransportEndpointThreshold)默认已启用 http 传输,因此 mcp_remote_transport 无需修改规范即可达到 10/10——只有当规范明确缩窄了列表时才需指出。完整参考请见 docs/SPEC-EXTENSIONS.md。
编辑规范后,重新生成(或将更改通过 regen-merge 合并到已发布的库中),以便新的 mcp: 块传递到模板中。通过 Cobratree 遍历发现的新命令无论如何都会作为 MCP 工具呈现;它们不需要修改规范。
经验法则:如果没有评分卡,你的修复仍然有价值,那就去做。如果唯一动机是“提高分数”,就不要做。
显示差异并输出结果块
向用户显示差异,然后输出结构化的 ---POLISH-RESULT--- 块。调用方技能(例如 main printing-press Phase 5.5)可借助此块可靠地解析建议和评分;上方的人类可读表格供用户查看。
Polish Results for <CLI_NAME>:
Before After Delta
Scorecard: XX/100 XX/100 +N
Verify: XX% XX% +N%
Live matrix: exercised/not_exercised -> exercised/not_exercised
Tools-audit: XX XX -N pending findings
Fixes applied:
- <one-line description of each fix>
Skipped findings:
- <finding>: <why you chose not to fix it>
Remaining issues:
- <one-line description of each issue you tried to fix but couldn't>
---POLISH-RESULT---
scorecard_before: <N>
scorecard_after: <N>
verify_before: <N>
verify_after: <N>
dogfood_before: <PASS|FAIL>
dogfood_after: <PASS|FAIL>
dogfood_live_matrix_before: <exercised|not_exercised|unknown>
dogfood_live_matrix_after: <exercised|not_exercised|unknown>
govet_before: <N>
govet_after: <N>
gosec_before: <N>
gosec_after: <N>
tools_audit_before: <N pending>
tools_audit_after: <N pending>
publish_validate_before: <PASS|FAIL|skipped (mid-pipeline)>
publish_validate_after: <PASS|FAIL|skipped (mid-pipeline)>
fixes_applied:
- <one-line description of each fix>
skipped_findings:
- <finding>: <why you chose not to fix it>
remaining_issues:
- <one-line description of each issue you tried to fix but couldn't>
ship_recommendation: <ship|ship-with-gaps|hold>
further_polish_recommended: <yes|no>
further_polish_reasoning: <one sentence explaining the call>
---END-POLISH-RESULT---
这三个列表用途各不相同:
- fixes_applied:已更改的内容——调用方会显示这些内容
- skipped_findings:发现但有意未修复的问题及其原因(例如,“verify 将
stale归类为 read——这是评分器 bug,不是 CLI 问题”,“version的 thin-short 已按原样接受——准确且简短”)。调用方会将这些内容呈现给用户,以便用户决定是否手动处理。 - remaining_issues:尝试修复但未能解决的问题。
publish_validate_* 值。 如果 polish 运行了 publish-validate(独立模式),则输出 PASS 或 FAIL。如果 polish 跳过了它(中途调用,STANDALONE_MODE=false),则输出字面字符串 skipped (mid-pipeline)。跳过值仅供参考:调用方在决定是否将 polish 的 ship_recommendation 传递为 CLI 级别的 hold 时,不得将其视为失败。
dogfood_live_matrix_* 值。 只有当 live-check 评估了至少一个真实样本时,才输出 exercised。对于仅使用 mock、无 token、无研究或没有已评估样本的运行,输出 not_exercised。当 dogfood_after: PASS 但 dogfood_live_matrix_after: not_exercised 时,人类可读摘要必须写明 dogfood PASS (mock only; live matrix not exercised — run the live gate before publish),且 ship_recommendation 必须为 hold,除非父调用方明确负责稍后运行 live gate。
gosec_* 值。 输出经过分流处理后,与此打印 CLI 仍相关的 gosec 问题数量。生成文件分流处理后,这些值有意不采用 /tmp/polish-gosec-*.json 中 Issues[] 的原始长度:不要将转入 skipped_findings 的生成器产生问题计为候选修复项,但要计入会导致 hold 的未解决手写问题。
选择 further_polish_recommended
根据判断,而不是根据 remaining_issues 的数量。当再次运行 polish 有实际机会解决遗留问题时,设为 yes:
remaining_issues包含你因时间不足而未解决的 verify 或 dogfood 失败,再次运行并对每个失败投入更多精力,有望解决这些问题。- 本次已完成的修复可能解锁了依赖项,但你来不及处理。
- SKILL/CLI 不匹配需要在本次修改源代码树后再次检查。
当再次运行只会重复同样的工作时,设为 no:
remaining_issues是只有用户才能决定的事项(重命名旗舰命令、选择默认行为、接受结构性权衡)。- 本次已用两种不同方式尝试修复,但都因同一原因失败。
- 阻碍来自外部因素(API 改变了结构、受到速率限制、缺少凭证),新的 polish 运行也不会有不同结果。
remaining_issues为空,且skipped_findings都与环境或结构有关——polish 已无事可做。
further_polish_reasoning 用一个句子说明理由,调用方会原样呈现。内容要具体(“analytics export 和 report show 的 verify 失败看起来可以解决,但我过早放弃了”),不要泛泛而谈(“再次运行 polish 可能会有帮助”)。调用方会依据此信号决定是否在下一条提示中提供“再次 Polish”选项;理由含糊,提示也会含糊。
发布选项
除非 STANDALONE_MODE 为 true,否则跳过整个部分。 根据调用方模式,STANDALONE_MODE 在上方的“Resolve CLI”代码块中设置:对于斜杠命令调用(/printing-press-polish ...)或在 args 中传入 --standalone 的 Skill 工具调用,值为 true;其他情况为 false。值为 false 时,polish 是从主 SKILL Phase 5.5 或 hold 路径“Polish to retry”中调用的,工作 CLI 尚未提升至库中。此时,/printing-press-publish <slug> 会解析为 $PRESS_LIBRARY/<slug>/,该目录要么为空,要么存有之前运行的过期内容——在此处调用 publish 要么无法解析,要么会发布错误的副本。此路径下的发布流程由父 Skill 负责;只需输出结果块并返回。
遵循发布的轮次边界规则:AskUserQuestion 的回答只能授权发送交接消息,不能授权在同一轮中发布。发布会新建或更新公共库 PR,因此必须等 polish 完成后,由用户发送一条新的消息。原因请参阅 references/publish-turn-boundary.md。
一个简单的检查:
if [ "$STANDALONE_MODE" != "true" ]; then
echo "non-standalone caller; skipping Publish Offer"
return
fi
门控依据是调用方模式标志,而不是解析后的路径。即使路径位于 $PRESS_LIBRARY/<slug>/ 下,没有 --standalone 的 Skill 工具调用也会延后发布;这是更安全的默认设置,也是确保在 polish 边界处捕获 Phase 5.5/5.6 反转失败模式(流水线中途运行触发公开 fork 和 PR)的唯一方式。之前基于路径子串的启发式判断(*.runstate/*)在此处已不再起关键作用——它仍保留在上方的研究目录解析代码块中,因为该代码块是在两种真实的磁盘布局之间进行选择,这与发布门控是不同的问题。
对于独立调用,请继续使用以下选项。
如果结果为 ship 或 ship-with-gaps:
根据结果块构造提示词。提示词形式由数据驱动,因此当 polish 已判定再处理一轮也无济于事时,不会再让用户权衡“再次 Polish”与“发布”。
建议
根据 polish 结果选择建议操作:
ship+remaining_issues为空 → 建议 发布。ship+remaining_issues不为空 +further_polish_recommended: yes→ 建议 再次 Polish。ship+remaining_issues不为空 +further_polish_recommended: no→ 如果剩余问题不涉及 CLI 的主要命令,则建议 发布;否则说明其中的取舍,让用户在 发布(按当前状态发布;对于ship判定,不会自动更新 README)和 完成之间决定。ship-with-gaps+further_polish_recommended: yes→ 建议 再次 Polish。ship-with-gaps+further_polish_recommended: no→ 建议 发布(差距已列入 README 的## Known Gaps,因为 polish 的 ship 逻辑对此类ship-with-gaps结果会强制执行——参见上方的“Ship logic”),如果该差距会阻止发布,则建议 完成——由 Agent 判断。
菜单
当 further_polish_recommended: no 时,完全隐藏“再次润色”选项。始终提供“发布”和“完成”。
当润色选择不建议再进行一轮时,将 further_polish_reasoning 作为上下文展示——用户应该能看到润色为何已完成。
通过 AskUserQuestion 呈现。以下是两种示例形式:
润色已收敛,结果良好(remaining_issues 为空,further_polish_recommended: no):
"<CLI_NAME> 已润色:评分卡 XX/100,验证 XX%。润色顺利完成——没有需要继续修复的问题。
建议:发布。
- 单独发布(推荐)——显示发布命令,供用户在下一条消息中发送
- 暂时完成——CLI 位于 $PRESS_LIBRARY/"
润色认为再来一轮会有帮助(remaining_issues 非空,further_polish_recommended: yes):
"<CLI_NAME> 已润色:评分卡 XX/100,验证 XX%。还剩 个问题。
润色备注:'<further_polish_reasoning>'
建议:发布前再次润色。
- 再次润色(推荐)——解决剩余的 个问题
- 单独发布——显示发布命令,供用户在下一条消息中发送,以按当前状态发布
- 暂时完成——CLI 位于 $PRESS_LIBRARY/"
推荐选项排在最前,带有 (recommended) 标签,且开头的 Recommendation: 一行明确说明 Agent 的建议。这三种强化方式让用户无需从选项顺序中推断建议。
如果选择“单独发布”
不要在同一轮中调用 /printing-press-publish <cli-name>,也不要在此处检查或创建公共库 PR。打印一条交接说明,要求用户明确发送新的消息。请包含 --from-polish 标记,以便发布操作在成功内联发布后,也能像过去的润色操作一样提供发布后的复盘尾声:
"发布需要单独确认,因为它可能会分叉
mvanhorn/printing-press-library、推送分支,并打开或更新 PR。要发布,请在下一条消息中发送:
/printing-press-publish <cli-name> --from-polish"
打印交接说明后,立即停止。如果用户在之后的消息中发送该命令,发布技能将负责验证、打包、创建或更新公共库 PR,以及提供 --from-polish 发布后复盘。
(当 STANDALONE_MODE 为 false 时,整个部分都不可达——本节顶部的 Publish Offer 防护会提前返回——因此此处无需额外检查。)
如果选择“再次润色”
使用同一个 CLI 重新运行 Phase 1 → Phase 2 → Phase 3。最多额外进行 2 轮润色(包括第一轮在内总计 3 轮)。
如果选择“暂时完成”
正常结束。
规则
- 修复所有问题。不要在修复前征求批准——润色是自主进行的。
- 如实报告结果。说明哪些方面有所改善,哪些没有。
- 不要添加新功能。润色用于修复质量问题,而非弥补功能缺失。
- 不要重新进行调研或生成。润色基于现有 CLI 开展。
- 不要修改 printing-press 生成器。那属于
/printing-press-retro。 - 不要修改
$CLI_DIR以外的任何文件。 - 如果润色添加或重命名了 Cobra 命令,MCP 接口会通过生成的
internal/mcp/cobratree运行时镜像自动更新。仅当 README/SKILL 的重点内容或注册表展示需要变化时才更新novel_features;仅用于调试的命令请使用cmd.Annotations["mcp:hidden"] = "true"。 - 每次润色调用最多进行 1 轮修复并重新诊断。“再次润色”路径会触发额外调用(总计最多 3 轮)。
- 优先采用机械式修复,而非创意性决策。如果需要创意性决策(例如 CLI 描述),且 manuscripts 中有研究简报,则使用该简报。