daily-fix: draft-PR recipe uses stale local main and omits -
kind: infra#wf-fix#wf-fix-fp:70197c634340#daily-auto-filed
track:Highlight text on any card (body, plan, or an event) to anchor a comment, or leave a whole-task comment here. Mention @claude to summon a reply.
No comments yet.
Overview / Motivation
Auto-filed by the /daily 2026-07-26 problem sweep (route 2). Surfaced by 5 independent miner group(s) over the 2026-07-26 session transcripts.
Goal
Fix the Step-4 draft-PR recipe in .claude/skills/issue/SKILL.md so its aheadness
pre-check compares against fetched origin/main, its gh pr create example carries
--title, and the site warns against piping the command.
Workflow gap
- Bug observed: the Step-4 draft-PR block gates on
rev-list --count main..issue-<N>against the repo root's STALE LOCALmain(worktrees are cut from fetchedorigin/main), so the guard reads a nonzero count on a branch with zero own commits and lets a doomedgh pr createfire — which itself exits 1 because the recipe omits--title, which non-interactiveghrequires; and the site carries no "never pipe this" reminder, so sessions keep re-adding| tailand trippingguard_piped_git_push.sh. - Why it is a workflow gap: all three are properties of the copy-paste recipe itself —
a session that follows SKILL.md verbatim reproduces all three deterministically, while a
session that improvises the
origin/main..form does not. - Confidence (emitter): high
- verified-at-filing:
Read .claude/skills/issue/SKILL.mdL2016-2026 (the named target block) — L2021if [ "$(git -C "$REPO_ROOT" rev-list --count main..issue-<N>)" -gt 0 ]; then, L2022gh pr create --draft --head issue-<N> --body "Closes task #<N>.". Per-target presence confirmed:grep -n 'rev-list --count main\.\.' .claude/skills/issue/SKILL.md→ 1 hit, L2021 (the only baremain..aheadness guard in the file);grep -c '\-\-title' <that block>→ 0 (absence-of-flag claim; the 0-hit IS the evidence); nopipe/tailwarning anywhere in L2016-2026. Supporting facts verified:grep -n 'origin/main\|base-local' scripts/new_worktree.sh→ L23-28 confirm new branches are cut fromrefs/remotes/origin/main(fetched), with--base-localthe explicit opt-out — so localmainis the WRONG base by construction;grep -n 'gh pr' .claude/hooks/guard_piped_git_push.sh→ the hook's own BLOCKED message at L363 namesgh pr merge|createexplicitly. Landed-fix check:git log --oneline --since='7 days ago' -- .claude/skills/issue/SKILL.mdshows no commit touching the draft-PR recipe. (2026-07-26)
Evidence
- Session
8571eca6, 2026-07-26T10:51:16Z → 10:51:36Z: followed the recipe verbatim onissue-1698. The guard readAHEAD=2on a branch with zero own commits, so thegh pr createinside fired and died twice over —Exit code 1 | AHEAD=2 | must provide --title and --body (or --fill …) when not running interactively, then, after supplying a title,pull request create failed: GraphQL: Head sha can't be blank, Base sha can't be blank, No commits between main and issue-1698— i.e. exactly the error the guard exists to prevent. Cost: 2 wasted tool calls + 1 diagnostic call ≈ 1 turn. Session06447a89used theorigin/main..issue-1691form instead and had no such failure; the two sessions diverged only because one followed the SKILL recipe verbatim. - Session
8380a48c, 2026-07-26T09:30:14Z: same shape onissue-1696with the diagnostic spelled out —Exit code 1 must provide --title and --body (or --fill or fill-first or --fillverbose) when not running interactively, followed byrev-list count (main..issue-1696): 1/rev-list count (origin/main..issue-1696): 0. The branch was byte-identical toorigin/main; only the stale local ref made the guard pass. Cost: one failedghcall + a full diagnostic round (~1 min), self-recovered. - Session
a2c4bae3at 2026-07-26T15:19:54Z and session0793d486at 2026-07-26T11:09:04Z: the--titlehalf alone, both from the verbatim recipe —Exit code 1 | must provide \--title` and `--body` (or `--fill` or `fill-first` or `--fillverbose`) when not running interactively. Counting: 2 tool_result FIRING events (text is the invokedghcommand's own output, deduped per tool call, one per session). Each cost a wasted turn and forced re-opening the PR later; the guard'selse` branch never printed because the command died first. - Session
67cf175e, 2026-07-26T15:53:29Z: same--titlefailure, retried by hand with a written title. Four sessions, one recipe. - Session
564d9a53, 2026-07-26T07:31:38Z: the pipe half. The session added| tail -3to the recipe'sgh pr createandguard_piped_git_push.shcorrectly BLOCKED it:"PreToolUse:Bash hook error: [.claude/hooks/guard_piped_git_push.sh]: BLOCKED: piping \git push` / `git merge` / `git commit` / `gh pr merge|create` through a filter masks the non-zero exit code…". Two aggravating details: SKILL.md gives the recipe UNPIPED, so the pipe is a composition habit the site does not warn against; and the piped call sat inside anifbranch that was FALSE (issue-1695 has no commits ahead of main yet), yet the text-based PreToolUse guard blocked the whole compound call, taking an unrelatedsession_progress_report.py` title refresh with it. Cost: one blocked call- one retry (~5 s).
Proposed change
Rewrite .claude/skills/issue/SKILL.md L2016-2026 as:
# Base ref is FETCHED origin/main — new_worktree.sh cuts branches from
# refs/remotes/origin/main, and the repo root's local `main` routinely lags it.
# NEVER pipe this block — guard_piped_git_push.sh blocks a piped `gh pr create`
# (CLAUDE.md § Concurrent repo-root committers): a pipe masks the exit code.
timeout --kill-after=30s 120s git -C "$REPO_ROOT" fetch origin main --quiet || true
if [ "$(git -C "$REPO_ROOT" rev-list --count origin/main..issue-<N>)" -gt 0 ]; then
gh pr create --draft --head issue-<N> \
--title "issue-<N>: <task title>" \
--body "Closes task #<N>."
else
echo "issue-<N> has no commits ahead of origin/main yet; skipping draft PR (open it after the implementer commits)."
fi
- Change the aheadness test from
main..issue-<N>toorigin/main..issue-<N>, preceded by a boundedgit fetch origin main(the same base ref every Step-10d guard already uses). - Add
--title "issue-<N>: <task title>"to thegh pr createexample (--fillis an acceptable alternative but loses the issue- title convention). - Add the inline "never pipe this" comment naming
guard_piped_git_push.shat the recipe site, so a composer does not re-add a filter. - Update the
else-branch echo to sayorigin/mainso the message matches the test. - Grep the SKILL for any other bare
main../main --refs inside guards while making this change and bring them onto the same base ref (compose-time grep found only L2021, but the planner should re-verify at plan time in case another lands in between).
Scope / surfaces
- Primary target:
.claude/skills/issue/SKILL.md - none
Constraints / invariants
- Workflow-surface only — never experiment code,
configs/, ortasks/. uv run python scripts/workflow_lint.pypasses (no-flags); ruff clean on touched files.- The
fetchmust stay bounded and non-fatal (timeout … || true) — a network hiccup at Step 4 must not halt the pipeline; a stale-but-presentorigin/mainstill beats localmain. - Do not remove the aheadness guard itself; the
No commits between main and issue-<N>failure it prevents is real, it was just checking the wrong ref. - This session runs under a
workflow_fix_target:Provenance line — it MUST NOT auto-route its own subagents' workflow-fix candidates (recursion guard).
Provenance
-
fingerprint: 70197c634340
-
workflow_fix_target: .claude/skills/issue/SKILL.md
-
fingerprint: PENDING
/daily 2026-07-26 route-2 filing. Miner refs: E-P1, G-P5, B-P3, J-P4, I-P9.
Activity