diff --git a/ship/sections/pr-body.md b/ship/sections/pr-body.md index c3e516415..f699e833d 100644 --- a/ship/sections/pr-body.md +++ b/ship/sections/pr-body.md @@ -186,11 +186,14 @@ printf '%s' "v$NEW_VERSION : " | ~/.claude/skills/gstack/bin/gsta HIGH blocks (exit 3, no skip). MEDIUM → AskUserQuestion (PII subset offers `--auto-redact`). Same scan runs before the `gh pr edit --body` path (Step 17). -**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent): +**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent). +`$PR_BODY_FILE` comes from the scan block above — restate it in this shell if +blocks ran separately, and never proceed with an empty file: ```bash # PR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } gh pr create --base --title "v$NEW_VERSION : " --body-file "$PR_BODY_FILE" rm -f "$PR_BODY_FILE" ``` @@ -201,7 +204,9 @@ rm -f "$PR_BODY_FILE" # MR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) # Send the SCANNED file's bytes — scan-at-sink means never re-render the body -# from a fresh heredoc (that reopens the scan-vs-send gap). +# from a fresh heredoc (that reopens the scan-vs-send gap). $PR_BODY_FILE comes +# from the scan block above; never proceed with an empty file. +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } glab mr create -b -t "v$NEW_VERSION : " -d "$(cat "$PR_BODY_FILE")" rm -f "$PR_BODY_FILE" ``` diff --git a/ship/sections/pr-body.md.tmpl b/ship/sections/pr-body.md.tmpl index ba42495c8..313714c3c 100644 --- a/ship/sections/pr-body.md.tmpl +++ b/ship/sections/pr-body.md.tmpl @@ -184,11 +184,14 @@ printf '%s' "v$NEW_VERSION : " | ~/.claude/skills/gstack/bin/gsta HIGH blocks (exit 3, no skip). MEDIUM → AskUserQuestion (PII subset offers `--auto-redact`). Same scan runs before the `gh pr edit --body` path (Step 17). -**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent): +**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent). +`$PR_BODY_FILE` comes from the scan block above — restate it in this shell if +blocks ran separately, and never proceed with an empty file: ```bash # PR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } gh pr create --base --title "v$NEW_VERSION : " --body-file "$PR_BODY_FILE" rm -f "$PR_BODY_FILE" ``` @@ -199,7 +202,9 @@ rm -f "$PR_BODY_FILE" # MR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) # Send the SCANNED file's bytes — scan-at-sink means never re-render the body -# from a fresh heredoc (that reopens the scan-vs-send gap). +# from a fresh heredoc (that reopens the scan-vs-send gap). $PR_BODY_FILE comes +# from the scan block above; never proceed with an empty file. +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } glab mr create -b -t "v$NEW_VERSION : " -d "$(cat "$PR_BODY_FILE")" rm -f "$PR_BODY_FILE" ``` diff --git a/test/fixtures/golden/codex-ship-SKILL.md b/test/fixtures/golden/codex-ship-SKILL.md index 19551d0af..588261067 100644 --- a/test/fixtures/golden/codex-ship-SKILL.md +++ b/test/fixtures/golden/codex-ship-SKILL.md @@ -2468,11 +2468,14 @@ printf '%s' "v$NEW_VERSION : " | $GSTACK_ROOT/bin/gstack-redact - HIGH blocks (exit 3, no skip). MEDIUM → AskUserQuestion (PII subset offers `--auto-redact`). Same scan runs before the `gh pr edit --body` path (Step 17). -**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent): +**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent). +`$PR_BODY_FILE` comes from the scan block above — restate it in this shell if +blocks ran separately, and never proceed with an empty file: ```bash # PR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } gh pr create --base --title "v$NEW_VERSION : " --body-file "$PR_BODY_FILE" rm -f "$PR_BODY_FILE" ``` @@ -2483,7 +2486,9 @@ rm -f "$PR_BODY_FILE" # MR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) # Send the SCANNED file's bytes — scan-at-sink means never re-render the body -# from a fresh heredoc (that reopens the scan-vs-send gap). +# from a fresh heredoc (that reopens the scan-vs-send gap). $PR_BODY_FILE comes +# from the scan block above; never proceed with an empty file. +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } glab mr create -b -t "v$NEW_VERSION : " -d "$(cat "$PR_BODY_FILE")" rm -f "$PR_BODY_FILE" ``` diff --git a/test/fixtures/golden/factory-ship-SKILL.md b/test/fixtures/golden/factory-ship-SKILL.md index 0758e4321..7aeb57466 100644 --- a/test/fixtures/golden/factory-ship-SKILL.md +++ b/test/fixtures/golden/factory-ship-SKILL.md @@ -2903,11 +2903,14 @@ printf '%s' "v$NEW_VERSION : " | $GSTACK_ROOT/bin/gstack-redact - HIGH blocks (exit 3, no skip). MEDIUM → AskUserQuestion (PII subset offers `--auto-redact`). Same scan runs before the `gh pr edit --body` path (Step 17). -**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent): +**If GitHub:** create from the SCANNED file (exact bytes scanned = bytes sent). +`$PR_BODY_FILE` comes from the scan block above — restate it in this shell if +blocks ran separately, and never proceed with an empty file: ```bash # PR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } gh pr create --base --title "v$NEW_VERSION : " --body-file "$PR_BODY_FILE" rm -f "$PR_BODY_FILE" ``` @@ -2918,7 +2921,9 @@ rm -f "$PR_BODY_FILE" # MR title MUST start with v$NEW_VERSION — enforced on every run, no exceptions. # (See Step 19 idempotency block + bin/gstack-pr-title-rewrite.sh for the rule.) # Send the SCANNED file's bytes — scan-at-sink means never re-render the body -# from a fresh heredoc (that reopens the scan-vs-send gap). +# from a fresh heredoc (that reopens the scan-vs-send gap). $PR_BODY_FILE comes +# from the scan block above; never proceed with an empty file. +[ -s "$PR_BODY_FILE" ] || { echo "ERROR: scanned body file missing/empty — re-run the scan block." >&2; exit 1; } glab mr create -b -t "v$NEW_VERSION : " -d "$(cat "$PR_BODY_FILE")" rm -f "$PR_BODY_FILE" ```