mcpField
P
printing-press-polish

printing-press-polish

github.com/mvanhorn测试与质量4.9k6.9k 次安装今天更新
代码仓库

关于 printing-press-polish

用于发布前检查和打磨 Printing Press 库中生成的 CLI 的技能。它在分叉上下文中运行,并指导版本兼容性检查、差异审查、验证和发布决策。

主要功能

  1. 01按名称或路径定位 CLI
  2. 02检查二进制版本兼容性
  3. 03检测与公共库的差异
  4. 04运行诊断和修复迭代
  5. 05应用发布门槛与发布流程

适用场景

  1. 01验证存在缺口后打磨生成的 CLI
  2. 02发布前审查库中的 CLI
  3. 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.md
publish-turn-boundary.md
tools-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(直接使用)

位置值的解析顺序:

  1. 如果是绝对路径或以 ~ 开头的路径,且路径存在,则使用该路径
  2. 尝试 $PRESS_LIBRARY/<arg>(精确匹配——适用于 redfin 这样的 slug)
  3. 如果带有 -pp-cli 后缀,移除该后缀,然后尝试 $PRESS_LIBRARY/<slug>(例如,redfin-pp-cli → redfin)
  4. 模糊搜索: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 确实会遇到的问题。

你必须:

  1. 定位公共库克隆。 如果设置了 $PRINTING_PRESS_LIBRARY_PUBLIC,则使用它;否则,按适合此平台的方式扫描用户的文件系统。通过检查 git remote 是否指向 mvanhorn/printing-press-library 来验证每个候选项——其他目录可能名称相同(例如 fork 或意外重名)。如果存在多个有效克隆,优先选择最近修改的;只有仍无法确定时才询问用户。

  2. 在克隆中定位此 CLI。 使用 find <clone>/library -type d -name "<api>-pp-cli" 或等效方法。

  3. 运行 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 是预期输出的一行,不值得为了过滤它而牺牲完整性。

  4. 继续之前,先展示检查结果。

结果:

  • 未找到克隆 → 用户本地没有公共库。明确说明这一点(“本地未找到公共库;将以内部分副本为准继续”),然后继续。
  • 找到克隆,但其中不包含此 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 --jsonpassed: 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 缺口scorecardREADME 得分 < 8
示例缺口dogfood缺少示例的命令
Go vet 问题go vet任何输出
输出实体警告scorecard JSONlive_check.features[].warnings — 面向用户的输出中包含原始 HTML 实体
输出合理性Phase 4.85Agent 输出审查发现的问题
MCP 工具质量tools-auditShort 为空、Short 内容单薄、缺少只读注释、MCP 描述内容单薄
客户 PIIpii-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 写入表中:

  1. 阅读待缓存资源对应的 internal/types/<resource>.go 和 internal/store/<resource>.go。只要这些文件生成了类型化插入/更新辅助函数,就应使用它们。如果生成的资源缺少辅助函数,应先创建辅助函数,再编写任何持久化代码。
  2. 在确定插入映射正确之前,对照规范架构和真实的响应示例检查响应结构。
  3. 持久化之前,将 API 响应解码为类型化结构体。除非目标表是手动编写的迁移中声明的 polish 自有自定义表(见下文原始 SQL 例外),否则不要根据非类型化的 map[string]any 或原始 json.RawMessage 构造 INSERT INTO ... 语句。
  4. 根据资源类型确认目标表,而不是根据新增命令最初使用的查询来判断。获取了 <child> 记录的命令必须插入 <child> 行,而不是父级行或相邻的便利表。
  5. 插入前规范化嵌套的响应标识符。如果 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 发现:

  1. 阅读引用的文件,并确认它是否为手工编写。若 internal/cli/、internal/syncer/ 或 internal/store/ 下的整个文件,其前 20 行不包含 Generated by CLI Printing Press,则该文件属于 polish 自有的新功能代码。
  2. 如果发现位于手工编写的代码中,先在源代码中修复根本原因,再处理优先级较低的 polish 项目。例如:用参数化查询替换 SQL 字符串拼接,避免使用不可信参数调用 shell,并将看起来像凭据的字面值移至配置或环境变量处理逻辑中。
  3. 如果 gosec 标记的是生成代码,不要手动编辑生成文件。应修复上游规范并重新生成,或者添加一条 skipped_findings,将其标记为生成器后续处理候选项,并注明规则 ID 和文件路径。
  4. 如果 gosec 报告的是误报,应保持抑制范围尽可能小并说明原因。只有在代码确实安全且理由长期有效时,才优先使用局部的 // #nosec G### -- reason;否则应修复代码。

手工编写的新功能 Go 代码中未解决的 gosec 发现属于硬性阻塞项:必须将其列入 remaining_issues,令 ship_recommendation: hold,并在修复可能通过机械方式完成时设置 further_polish_recommended: yes。

优先级 2:验证失败

对于任何 dry-run 或 exec 验证失败的命令:

  1. 阅读命令文件
  2. 查找 Args: cobra.ExactArgs(N) 或类似约束
  3. 移除 Args: 字段
  4. 在 RunE 开头添加:
    if len(args) == 0 {
        return cmd.Help()
    }
    
  5. 对于需要 2 个或更多参数的命令,使用 if len(args) < 2
  6. 检查 dry-run 是否会因数据为 nil 而崩溃,并添加保护:
    if flags.dryRun {
        return nil
    }
    
优先级 3:死代码
  1. 对于 dogfood 标记的每个死函数,搜索所有 .go 文件以确认它确实未被使用(而不只是定义本身匹配到)
  2. 如果确实未使用:删除该函数
  3. 如果被其他辅助函数使用:保留(属于误报)
  4. 删除函数后,移除未使用的导入
  5. 删除过时文件(已提升但未在 root.go 中注册的命令)
优先级 4:CLI 描述和元数据
  1. 阅读 internal/cli/root.go 中根命令的 Short
  2. 如果包含模板化内容(“Reverse-engineered...”或原始 API 标题),请改写: 模式:"<Product> CLI with <capability-1>, <capability-2>, and <capability-3>"
  3. 检查命令是否缺少 Example 字段。添加包含领域专属值的真实示例。
优先级 5:README

首要规则:README 中列出的每条命令都必须运行 <cli> <cmd> --help。 不要臆测标志名称、参数格式或有效值。如果你写了 --start-time,但标志实际是 --start,那么 README 就是错误的,用户第一次尝试时就会报错。

已渲染部分的事实来源文件

编辑 README.md、SKILL.md 或 .printing-press.json 之前,请先确认该部分是否由源文件渲染生成。Dogfood 和重新生成会覆盖这些已渲染部分,因此直接修改只是暂时的,仅应在检查当前输出时使用。

已渲染部分或字段事实来源文件::字段润色工作流
README ## Unique Featuresresearch.json::novel_features_built[]编辑底层 research.json 中的功能描述/示例,然后使用 --research-dir 重新运行 dogfood。
SKILL ## Unique Capabilitiesresearch.json::novel_features_built[]编辑底层 research.json 中的功能描述/示例,然后使用 --research-dir 重新运行 dogfood。
internal/mcp/tools.go command_mirror_capabilitiesresearch.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 区块会保持不变。

必需章节(必须完整且正确)
  1. 标题:# <产品名称> CLI——使用产品的真实名称,并确保大小写和标点正确(例如,使用“Cal.com”,而不是“Cal Com”)
  2. 副标题:用一句话描述该 CLI 为用户提供的功能,并与根目录中的 Short 字段一致。不要描述 API。
  3. 安装:正确的安装命令。使用 printing-press-library 仓库 URL,而不是不存在的单个 CLI 仓库 URL。
  4. 身份验证:说明如何设置 <API>_API_KEY 环境变量,以及从哪里获取密钥(链接到提供商的设置页面);如果支持自托管 URL 覆盖,也要说明。阅读 config.go,找出所有环境变量。
  5. 快速入门:提供 3–5 条用户实际会首先运行的命令。选择既最实用(日常会运行),又能展现 CLI 的价值(说明为何要安装它,而不是使用 curl)的命令。通常包括: doctor → sync → 超越基础功能的命令(today、health)→ search。避免使用原始列表命令——这类命令只会输出数据,无法体现 CLI 存在的意义。
  6. 命令:按类别整理成表格。按领域功能分组(Scheduling、Analytics、Account、Utilities),而不是按实现结构分组。
  7. 输出格式:展示 --json、--select、--csv、--compact、--dry-run、--agent。使用真实命令,而不是占位符。
  8. Agent 用法:说明适用于 Agent 的特性和退出代码。
  9. 操作指南:提供 8–15 个示例,使用经 --help 验证的标志名称。展示 CLI 的独特功能:超越基础功能的命令、筛选器、SQL 查询、管道。至少包含一个修改示例。
  10. 健康检查:展示实际的 doctor 输出,而不是占位符。
  11. 配置:列出 config.go 中的所有环境变量并附上说明。包含配置文件路径。
  12. 故障排除:将常见错误与退出代码对应,并提供解决方法。
可选章节(酌情添加)
  • 速率限制:如果 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 调用的命令。两种修复方法:
    1. 如果该标志是通过 addXxxFlags(cmd, ...) 之类的共享辅助函数添加的,请将 cmd.Flags().StringVar(...) 声明直接内联到受影响命令的源文件中。verify-skill 的 grep 无法跟踪函数调用的间接关系。
    2. 如果 SKILL 示例确实有误,请将示例改为使用该命令已声明的标志。
  • positional-args — got N positional args; Use: "<cmd> <arg>" expects M-M。SKILL 操作说明传入了 N 个位置参数,但命令的 Use: 声明要求 M 个参数。两种修复方法:
    1. 如果命令也接受通过 --flag 传入值,请将 Use: "cmd <arg>" 改为 Use: "cmd [arg]"(方括号表示可选参数)。对于声明为可选位置参数的命令,verify-skill 会正确接受仅使用 --flag 的调用。
    2. 如果 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)不会发现这类问题。

请暂停并:

  1. 运行 "$PRINTING_PRESS_BIN" tools-audit "$CLI_DIR" --json,查看机械检查结果(Short 为空、Short 过于简略,以及名称类似读取操作的命令缺少 mcp:read-only)。
  2. 你必须阅读 references/tools-polish.md,并按照其中的说明处理检查结果,还要对每条命令进行判断审查——无论审计是否标记了该命令。审计只能发现机械性问题;描述质量以及边界分类(只读还是本地写入)始终需要 Agent 进行判断。不得跳过此步骤。
  3. 接受 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 邮编以及邮寄地址等模式。

请暂停并:

  1. 运行 "$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。
  2. 你必须阅读 references/pii-polish.md,并按照其中针对每条问题的决策树操作——在源文件中将真实信息替换为不会匹配的占位符,或者填写决策前字段 category 和 evidence_context 后接受该问题。
  3. 接受 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 之前:

    1. 阅读 CLI 的 README.md。如果已存在 ## Known Gaps 章节(例如主 SKILL 阶段 4 在润色开始前已写入),确认其中涵盖 remaining_issues 中面向用户的条目。为润色过程中发现的任何新用户可见缺陷添加项目符号。

    2. 如果缺少 ## Known Gaps,则添加该章节,放在 ## Quick Start 之后(或 ## Usage 之前),以符合 ## Unique Features 的位置惯例。remaining_issues 中每项面向用户的内容都单独列为一条。请从用户的角度描述:哪个命令行为异常,以及可用什么方法绕过。示例:

      ## Known Gaps
      
      - **`analytics export --csv`** 在事件数超过 10k 的工作区中会返回被截断的行。在底层导出端点实现分页之前,请使用 `--json` 并通过管道传给 `jq` 作为替代方法。
      
    3. 填充该部分时,筛选 remaining_issues,只保留面向用户的条目。内部事项(例如验证已弃用标志是否存在偏差、调整 MCP 描述、润色内部备注)不属于公开的“已知问题”。如果 Agent 无法从 remaining_issues 中识别出任何面向用户的问题,结论应为 ship,而不是 ship-with-gaps。

    4. 在 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)。

更进一步,但不要弄虚作假

发布门槛是底线,而非上限。通过门槛后,请检查仍未达到满分的评分卡维度,并判断每项差距是真实问题还是结构性因素:

  1. 找到根本缺陷,而不是盯着分数。 评分卡是质量的衡量指标,而不是目标本身。README 得分为 8/10,可能是缺少 Cookbook 部分或命令已过时——这是实际存在且可以修复的问题。mcp_surface_strategy 在拥有 200 个端点的 API 上得分为 2/10,可能是在指出其接口大多只是端点镜像——这也可能可以改进。
  2. 如果有真正有价值的 Agent 级改进,就着手完成。 改进描述、补充缺失的标志说明、完善薄弱的 README 部分,或添加能反映实际用法的示例。CLI 会变得更好,分数也会随之提高。
  3. 如果是结构性缺陷,就记录并接受。 某些维度假设 CLI 所属领域具备它并不具备的能力(例如,用写入工作流维度评估只读 API,用认证维度评估没有认证机制的 CLI,或用针对大型 API 校准的 surface_strategy 门槛惩罚小型 API)。在 skipped_findings 中注明原因,然后继续。
  4. 绝不要为了满足评分器而添加脚手架。 虚构命令、测试、标志,或纯粹为了提高分数而写的模板化文字,都会损害 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_transportmcp.transporttransport: [stdio, http](端点数不超过 spec.DefaultRemoteTransportEndpointThreshold 的小型 API 默认已启用此项;仅当规范选择了更窄的列表,或 API 超过阈值但仍需要远程访问时,才需要覆盖)
mcp_token_efficiency、mcp_surface_strategymcp.endpoint_tools、mcp.orchestrationendpoint_tools: hidden + orchestration: code(Cloudflare 模式:将约 70 个原始端点工具精简为 <api>_search + <api>_execute;所有端点仍可通过 execute 访问)
mcp_tool_designmcp.intents为 API 支持的工作流定义多步骤意图组合
mcp_description_qualitymcp-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%。润色顺利完成——没有需要继续修复的问题。

建议:发布。

  1. 单独发布(推荐)——显示发布命令,供用户在下一条消息中发送
  2. 暂时完成——CLI 位于 $PRESS_LIBRARY/"

润色认为再来一轮会有帮助(remaining_issues 非空,further_polish_recommended: yes):

"<CLI_NAME> 已润色:评分卡 XX/100,验证 XX%。还剩 个问题。

润色备注:'<further_polish_reasoning>'

建议:发布前再次润色。

  1. 再次润色(推荐)——解决剩余的 个问题
  2. 单独发布——显示发布命令,供用户在下一条消息中发送,以按当前状态发布
  3. 暂时完成——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 中有研究简报,则使用该简报。

评论

支持 Markdown