diff --git a/plugins/source-control/.claude-plugin/plugin.json b/plugins/source-control/.claude-plugin/plugin.json index e75728ed7..dce220504 100644 --- a/plugins/source-control/.claude-plugin/plugin.json +++ b/plugins/source-control/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json", "name": "source-control", - "version": "0.13.0", + "version": "0.13.1", "description": "Git and GitHub delivery workflow: /commit (Conventional Commits + Co-Authored-By trailer via safe heredoc mechanics), /pull-request (prep, create, CI monitoring, review-comment triage, merge, CI-log fetch), /babysit-prs (self-pacing fleet loop — safe by default; opt-in worker/autopilot tiers add gate-checked merge and thread resolution behind a deterministic Python engine), /worktree (create, status, cleanup, audit for parallel-session isolation), /setup (check the effective commit-subject / PR-title convention and babysit-prs config, or apply — interview the repo and write the tracked convention config), and /resolve-conflicts (intent-first merge/rebase conflict resolution with a semantic-conflict sweep — never --abort). The commit-subject / PR-title convention is configurable per repo via a tracked .claude/source-control.md config written by a re-runnable setup skill; Conventional Commits is the default when no convention is declared.", "author": { "name": "Melodic Software", diff --git a/plugins/source-control/CHANGELOG.md b/plugins/source-control/CHANGELOG.md index a89192920..40b051a80 100644 --- a/plugins/source-control/CHANGELOG.md +++ b/plugins/source-control/CHANGELOG.md @@ -3,6 +3,25 @@ All notable changes to the `source-control` plugin are documented here. Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); this plugin uses semantic versioning. +## [0.13.1] + +### Fixed + +- **`pull-request` create flow now scaffolds a non-empty `## Related` section in the assembled PR + body.** The create flow builds the PR body from its own template and passes it via `gh pr create + --body`, which fully overrides `.github/pull_request_template.md` (cli/cli#10751) — so + skill-driven PRs never see a repo PR template. The assembled skeleton had `## Summary` / + `## Test plan` but no `## Related` section, so PRs in a repo whose CI enforces a + `pr-issue-linkage`-style contract (non-empty `## Related` + a native closing keyword) failed the + gate on first push and burned a red-CI round-trip. The template now emits a `## Related` section + defaulting to the literal `N/A` (non-empty by default; replace with `Refs #N` references to + related-but-not-closed PRs/ADRs/decisions when they exist), pairing with the always-present + `${CLOSES_LINE}` closing keyword so both halves of the contract are scaffolded up front. This is + the create-flow half of the same gap the repo PR template covers for the web/editor authoring + path. The §2.4.1 prose documents both scaffolds and flags that a bare `Refs #N` opt-out does not + satisfy a validator's closing-keyword half (only a real keyword or a `No linked issue` / + `No related issue:` phrase does). + ## [0.13.0] ### Changed diff --git a/plugins/source-control/skills/pull-request/reference/create.md b/plugins/source-control/skills/pull-request/reference/create.md index de5bcc393..d006eb3ca 100644 --- a/plugins/source-control/skills/pull-request/reference/create.md +++ b/plugins/source-control/skills/pull-request/reference/create.md @@ -159,7 +159,7 @@ Persist chosen line(s) into `${CLOSES_LINE}`. NEVER wrap a closing keyword in an git push -u origin ``` -Derive PR title from the commit subject, shaped to satisfy the resolved subject/title convention (SKILL.md §"PR title format" ladder: `.claude/source-control.md` → project convention → Conventional Commits default). Build body with `${CLOSES_LINE}` at top, followed by Summary + Test plan + Claude Code attribution: +Derive PR title from the commit subject, shaped to satisfy the resolved subject/title convention (SKILL.md §"PR title format" ladder: `.claude/source-control.md` → project convention → Conventional Commits default). Build body with `${CLOSES_LINE}` at top, followed by Summary + Test plan + a `## Related` section + Claude Code attribution: ```bash # Quoted heredoc — body template is inert; nothing inside expands. @@ -171,6 +171,9 @@ TEMPLATE=$(cat <<'EOF' ## Test plan - ... +## Related +N/A + 🤖 Generated with [Claude Code](https://claude.com/claude-code) EOF ) @@ -190,6 +193,13 @@ BODY+="$TEMPLATE" `gh pr create --body` fully overrides `.github/PULL_REQUEST_TEMPLATE.md` (cli/cli #10751) — body assembly above is the canonical path for skill-driven PRs; the template is the web-UI backstop. When the consuming project ships a PR template, mirror its section shape in the assembled body. +**Linkage scaffolds — always emitted.** Two scaffolds mirror the two-part contract a `pr-issue-linkage`-style gate enforces (a non-empty `## Related` section AND a native GitHub closing keyword or `No related issue:` opt-out), so a skill-driven PR clears that gate on first push instead of burning a red-CI round-trip: + +- **Closing-keyword line** (`${CLOSES_LINE}` at top): always populated by §2.4.0 (branch-derived `Closes #N`, the multi-issue prompt, or the orphan-PR opt-out) and asserted by the §2.4.2 gate before create — a required, always-present scaffold, not a conditional decoration. +- **`## Related` section**: defaults to the literal `N/A` so the section is non-empty by default. Replace `N/A` with genuinely related-but-not-closed references — sibling PRs, ADRs, or decision-log entries (`Refs #N — `, matching the repo's own `## Related` convention) — whenever they exist; leave `N/A` only when nothing else applies. The issue this PR *closes* belongs on the closing-keyword line, not here. + +Note the opt-out asymmetry: a `pr-issue-linkage` validator honors only a real closing keyword or a literal `No linked issue` / `No related issue:` phrase for its closing-keyword half — a bare `Refs #N` opt-out (§2.4.0 option 2) does **not** satisfy it. When the branch resolves a real `Closes #N` (the common path) both halves pass; a `Refs #N`-only PR still needs a `No related issue:` line to clear the gate. + ### 2.4.2 Verify closing-keyword line (pre-create gate) Before invoking `gh pr create`, grep assembled `$BODY` for a valid closing keyword OR an opt-out marker. Catches branches where §2.4.0 fell through (issue-existence check failed without orphan-PR prompt running, user dismissed the prompt, `$CLOSES_LINE` is empty) and prevents shipping a PR with no linkage signal.