[object Object]

← back to Cli Printing Press

fix(skills): polish syncs novel_features; publish detects squash-zombie branches (#414)

fe5d65c5178985b2e22331692ac7f2e2b6b4e240 · 2026-04-29 21:57:35 -0700 · Trevin Chow

Two related fixes surfaced during a scrape-creators publish (printing-press-library #156):

1. Polish skill now passes --research-dir to dogfood (#412). Without it,
   checkNovelFeatures returns Skipped and SyncCLIManifestNovelFeatures
   never runs, so legacy CLIs whose .printing-press.json predates the
   novel_features schema fail publish-validate's transcendence gate
   even after a clean polish.

2. Publish skill drops --author @me from the merged-PR collision check
   (#413). The filter caused the skill to miss cross-author merged PRs
   and squash-zombie branches (squash-merge leaves the source branch
   behind on remote with pre-squash refs that look "ahead of main" but
   are content-equivalent to the squash commit). Without detection,
   the skill misclassifies as fresh-publish, then git push -u fails on
   the existing remote branch. Timestamping handles both cases.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit fe5d65c5178985b2e22331692ac7f2e2b6b4e240
Author: Trevin Chow <trevin@trevinchow.com>
Date:   Wed Apr 29 21:57:35 2026 -0700

    fix(skills): polish syncs novel_features; publish detects squash-zombie branches (#414)
    
    Two related fixes surfaced during a scrape-creators publish (printing-press-library #156):
    
    1. Polish skill now passes --research-dir to dogfood (#412). Without it,
       checkNovelFeatures returns Skipped and SyncCLIManifestNovelFeatures
       never runs, so legacy CLIs whose .printing-press.json predates the
       novel_features schema fail publish-validate's transcendence gate
       even after a clean polish.
    
    2. Publish skill drops --author @me from the merged-PR collision check
       (#413). The filter caused the skill to miss cross-author merged PRs
       and squash-zombie branches (squash-merge leaves the source branch
       behind on remote with pre-squash refs that look "ahead of main" but
       are content-equivalent to the squash commit). Without detection,
       the skill misclassifies as fresh-publish, then git push -u fails on
       the existing remote branch. Timestamping handles both cases.
    
    Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 skills/printing-press-polish/SKILL.md  | 28 +++++++++++++++++++++++++---
 skills/printing-press-publish/SKILL.md |  6 ++++--
 2 files changed, 29 insertions(+), 5 deletions(-)

diff --git a/skills/printing-press-polish/SKILL.md b/skills/printing-press-polish/SKILL.md
index 832246c6..c29b3cec 100644
--- a/skills/printing-press-polish/SKILL.md
+++ b/skills/printing-press-polish/SKILL.md
@@ -101,7 +101,7 @@ echo "Polishing: $CLI_NAME"
 echo "Location: $CLI_DIR"
 ```
 
-### Find spec
+### Find spec and research dir
 
 ```bash
 API_SLUG="${CLI_NAME%-pp-cli}"
@@ -119,6 +119,25 @@ SPEC_FLAG=""
 if [ -n "$SPEC_PATH" ]; then
   SPEC_FLAG="--spec $SPEC_PATH"
 fi
+
+# Locate the research dir (parent of the spec's research/ folder, i.e.
+# manuscripts/<api>/<run-id>/). 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.
+RESEARCH_DIR=""
+for d in "$PRESS_HOME/manuscripts/$API_SLUG"/*/research.json "$PRESS_HOME/manuscripts/$CLI_NAME"/*/research.json; do
+  if [ -f "$d" ]; then
+    RESEARCH_DIR="$(dirname "$d")"
+    break
+  fi
+done
+
+RESEARCH_FLAG=""
+if [ -n "$RESEARCH_DIR" ]; then
+  RESEARCH_FLAG="--research-dir $RESEARCH_DIR"
+fi
 ```
 
 ### Divergence check
@@ -162,8 +181,11 @@ cd "$CLI_DIR"
 # Build
 go build -o "$CLI_NAME" ./cmd/"$CLI_NAME" 2>&1
 
-# Diagnostics. SPEC_FLAG is set in the "Find spec" step above.
-printing-press dogfood --dir "$CLI_DIR" $SPEC_FLAG 2>&1
+# Diagnostics. SPEC_FLAG and RESEARCH_FLAG are set in the "Find spec
+# and research dir" step above. RESEARCH_FLAG enables dogfood to
+# verify novel features and sync them into .printing-press.json
+# (required for publish-validate's transcendence gate).
+printing-press dogfood --dir "$CLI_DIR" $SPEC_FLAG $RESEARCH_FLAG 2>&1
 printing-press verify --dir "$CLI_DIR" $SPEC_FLAG --json 2>&1
 printing-press workflow-verify --dir "$CLI_DIR" --json > /tmp/polish-workflow-verify.json 2>&1 || true
 printing-press verify-skill --dir "$CLI_DIR" --json > /tmp/polish-verify-skill.json 2>&1 || true
diff --git a/skills/printing-press-publish/SKILL.md b/skills/printing-press-publish/SKILL.md
index 637192c1..6cc351e7 100644
--- a/skills/printing-press-publish/SKILL.md
+++ b/skills/printing-press-publish/SKILL.md
@@ -407,14 +407,16 @@ gh pr list --repo mvanhorn/printing-press-library --head "$HEAD_REF" --state ope
 
 If found, record `OWN_PR=true`, store `EXISTING_PR_NUMBER` and `EXISTING_PR_URL`.
 
-**If no open PR was found**, also check for a previously merged PR on the same branch:
+**If no open PR was found**, also check for a previously merged PR on the same branch — by ANY author, not just yours:
 
 ```bash
-MERGED_PR=$(gh pr list --repo mvanhorn/printing-press-library --head "$HEAD_REF" --state merged --author @me --json number --jq '.[0].number' 2>/dev/null)
+MERGED_PR=$(gh pr list --repo mvanhorn/printing-press-library --head "$HEAD_REF" --state merged --json number --jq '.[0].number' 2>/dev/null)
 ```
 
 If `MERGED_PR` is non-empty, the branch name was already used and merged. Set `BRANCH_MERGED=true` so Step 8 creates a new branch name (e.g., `feat/<api-slug>-YYYYMMDD`) instead of reusing the merged branch. Do NOT force-push onto a merged branch — `gh pr edit` would silently update a closed PR nobody is watching.
 
+The author-agnostic lookup also catches **squash-zombie branches**: GitHub squash-merge leaves the source branch behind on the remote, with pre-squash commit refs that look "ahead of main" but are content-equivalent to the squash commit. Without this check, the skill misclassifies the zombie as fresh-publish, then `git push -u` fails because the remote branch already exists. Timestamping sidesteps the issue entirely.
+
 ### No collision
 
 If no merged CLI exists and no open PRs match (other than your own), set `EXISTING_PR_NUMBER` from the own-PR check (or empty if none) and proceed to Step 8 normally.

← cb91024d fix(cli): OpenAPI parser prefers description over summary on  ·  back to Cli Printing Press  ·  chore(main): release 3.0.0 (#356) 10fd0405 →