Skip to content

feat: add source-control plugin (commit, pull-request, worktree skills)#72

Merged
kyle-sexton merged 18 commits into
mainfrom
feat/publish-source-control
Jul 11, 2026
Merged

feat: add source-control plugin (commit, pull-request, worktree skills)#72
kyle-sexton merged 18 commits into
mainfrom
feat/publish-source-control

Conversation

@kyle-sexton

@kyle-sexton kyle-sexton commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Refs melodic-software/medley#1283. Supersedes #63 (closed — GitHub Actions stopped creating workflow runs for that PR's pushes, so its required ci-status check could never re-run; all review findings there are fixed and all threads resolved).

Migrates the medley commit, pull-request, and worktree skills into one repo-agnostic source-control plugin (per the migration playbook per-plugin gate + acceptance security review). Worker: MELO-LAP-001-20260711T105548Z-20263.

What ships

  • plugins/source-control/ — 3 skills: /source-control:commit, /source-control:pull-request (prep/create/monitor/comments/merge/status/full/fetch-logs/babysit), /source-control:worktree (create/status/cleanup/audit); 6 bundled scripts + black-box tests + self-contained test-helpers.sh
  • Marketplace entry (category: development, tags incl. delivery) + root README row

De-coupling (medley → repo-agnostic)

  • Consumer conventions (commit-msg hook, branch naming, PR template, merge style, bot-reply identity) read from consumer CLAUDE.md/rules; Conventional Commits + squash merge remain defaults only; default branch resolved via gh repo view --json defaultBranchRef (never hardcoded main)
  • Medley skill/agent refs → "Adapting to your environment" graceful-degrade language; sibling refs among the 3 bundled skills stay bare per the locked decision
  • Medley tools/github-events channel infra → generic "GitHub-events push channel (MCP)" tier with Monitor-tool and cloud gh-poll fallbacks
  • gh-bot.sh / melodic-ai[bot] → "your posting identities"; babysit readiness gate resolves self via gh api user + --self / BABYSIT_SELF_LOGINS
  • .work/<slug>/ artifacts → working-notes location / ${CLAUDE_PLUGIN_DATA}; script paths via ${CLAUDE_PLUGIN_ROOT}; test fixtures use example-org/example-repo; integration tests require explicit INTEGRATION_REPO(+_RUN_ID)
  • Medley-only pitch action dropped (bound to medley conventions with no portable seam)

Review hardening on #63 (19 findings, 7 Codex/Claude rounds — all fixed + replied + thread-resolved)

Fork-safe checkout (gh pr checkout <N>) and head-repo pushes; WIP-safe babysit checkout (never reset/clean foreign WIP; own-branch no-op); terminal-only rebase states with safe read-only fallback; all-3-surface comment watching with fetch-success watermark; real gh pr checks bucket vocabulary; inline-reply verification on the correct API surface; table-row-only classification counting in the readiness gate (+ phantom-finding exclusion, regression-tested); review-body reaction exemption; untruncated log fetcher in the readiness gate; no-PR smart-default routing to prep.

Gate evidence (speed-adjusted per issue)

  • claude plugin validate --strict ./plugins/source-control → PASS; catalog validate --strict . → PASS
  • claude --plugin-dir ... plugin details source-control → always-on ~453 tok (commit ~130, pull-request ~160, worktree ~160)
  • --plugin-dir smoke test in a clean non-medley repo: /source-control:worktree status resolved as source-control:worktree, no permission errors, correct output
  • Plugin test suite: 43/43 gate tests + all script suites pass locally; shellcheck/shfmt/markdownlint/typos/lychee clean
  • Security review: skills-only — no hooks, no MCP servers, no telemetry, no outbound network beyond git/gh; GitHub writes only inside documented /pull-request phases; merge always behind a human gate

Note: advisor tool was unavailable this session (harness-level); proceeded per non-interactive fallback.


Note

Medium Risk
Large instruction surface that can drive commits, pushes, PR creation, and merge via gh; mitigated by documented human gates and no auto-merge, but agents following the skills still have real repo write capability.

Overview
Introduces the source-control Claude Code plugin and registers it in .claude-plugin/marketplace.json and the root README.

/source-control:commit documents Conventional Commits (consumer overrides), subject pre-check, Co-Authored-By trailers, Bash heredoc git commit, surgical staging, and pathspec-limited commits for shared indexes.

/source-control:pull-request is the bulk of the change: phased prep → create → monitor → merge, plus babysit, fetch-logs, and status/full flows. Reference docs enforce verified review findings, research-gated CI fixes, six-gate merge readiness, mandatory monitor checklists, and graceful degradation when optional review/research/MCP push channels are absent. Create adds validated Closes #N assembly, quoted-heredoc PR bodies, and composition with /commit.

Bundled scripts (with black-box tests): discover-prs.sh, fetch-all-pr-comments.sh, fetch-annotations.sh, babysit-readiness-gate.sh (mechanical finding vs classification-row coverage), plus related CI log helpers referenced in the skill. /source-control:worktree is described in the plugin manifest/README for create/status/cleanup/audit parallel-session workflows.

Design is repo-agnostic: ${CLAUDE_PLUGIN_ROOT} paths, gh-resolved default branch, optional env vars (BABYSIT_SELF_LOGINS, WORKTREE_STALE_DAYS, fetch-log overrides), skills-only surface (no hooks/MCP), and GitHub writes scoped to documented PR phases with merge behind a human gate.

Reviewed by Cursor Bugbot for commit b7fd0c7. Bugbot is set up for automated code reviews on this repo. Configure here.

kyle-sexton and others added 15 commits July 11, 2026 07:37
Migrates the medley commit, pull-request, and worktree skills into one
repo-agnostic delivery plugin. De-couplings: consumer conventions
(commit-msg hook, branch naming, PR template, merge style, bot identity)
read from the consuming project's CLAUDE.md/rules; push-channel monitoring
generalized to any GitHub-events MCP channel with Monitor-tool and gh-poll
fallbacks; bundled scripts write scratch to CLAUDE_PLUGIN_DATA and carry a
self-contained test-helpers.sh; babysit self-identity resolved from
gh api user (+ BABYSIT_SELF_LOGINS/--self override).

Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
…ontrol

# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
…rface watch polling, clean-tree rebase ordering)

Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
…eply verify surface, table-row classification counting)

Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
…ontrol

# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
…safe gh pr checkout, safe rebase-state fallback, inline follow-up verify surface, watermark on fetch success, phantom-finding exclusion, no-PR smart-default routing)

Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
…ontrol

# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
…hase, fork-safe babysit checklist checkout, untruncated log fetcher in readiness gate)

Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
…-branch resolution in create + babysit rebases)

Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
…ontrol

# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_7b481b8f-6bbe-43bb-bb94-ca53d2814ce6)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 4m 20s —— View job


PR Review: feat/publish-source-control

  • Read changed files and gather context
  • Review plugin manifest and marketplace entry
  • Review skill files (commit, pull-request, worktree)
  • Review shell scripts and tests
  • Check repo-agnosticism and security posture
  • Post findings

Summary

This is a large, well-engineered plugin migration. The skills are thoroughly documented, the shell scripts are carefully written with proper quoting, NUL-delimited find loops, and explicit error handling. Repo-agnosticism is solid: ${CLAUDE_PLUGIN_ROOT}, ${CLAUDE_PLUGIN_DATA}, gh repo view for all repo resolution, and no hardcoded paths. Security posture is clean — no hooks, no MCP servers, no outbound writes beyond git/gh, and all GitHub writes are behind documented human gates.

Five findings below, ranging from a real resource leak to minor documentation gaps.


Findings

1. Resource leak — scratch dir and job log file never cleaned up in fetch-failed-logs.sh

File: plugins/source-control/skills/pull-request/scripts/fetch-failed-logs.sh

When both $CLAUDE_PLUGIN_DATA and $FETCH_LOGS_SCRATCH are unset, $SCRATCH is set via mktemp -d (line 238). The ZIP file at $ZIP_PATH is removed on exit when KEEP_ZIP=0, and $EXTRACT_DIR is cleaned by trap cleanup_extract EXIT. But the $SCRATCH directory itself is never removed — an empty tmpdir leaks on every invocation outside a plugin-installed context.

The same applies in --job mode: $out_path ($SCRATCH/job-${JOB_ID}-logs.txt) is never removed regardless of KEEP_ZIP.

In practice, $CLAUDE_PLUGIN_DATA will be set when the plugin is installed, so real users aren't affected. But ad-hoc invocations and the test suite both hit the leak path. Suggested fix — track whether SCRATCH came from mktemp and conditionally clean it:

SCRATCH_IS_TEMP=0
if [[ -z "$SCRATCH" ]]; then
  if [[ -n "${CLAUDE_PLUGIN_DATA:-}" ]]; then
    SCRATCH="$CLAUDE_PLUGIN_DATA/scratch"
  else
    SCRATCH=$(mktemp -d)
    SCRATCH_IS_TEMP=1
  fi
fi

Then in the exit cleanup, when KEEP_ZIP=0 and SCRATCH_IS_TEMP=1, rm -rf "$SCRATCH".

Fix this →


2. Phase 0 smart-default step numbering skips step 4 in SKILL.md

File: plugins/source-control/skills/pull-request/SKILL.md

The numbered list under Phase 0 / Smart default reads 1. … 2. … 3. … 5. … 6. — step 4 is absent. The comment "skip steps 3-6 entirely" in step 2a implies step 4 was intentional at some point. Whether this was a merge artifact or deliberate removal, the current list leaves readers searching for missing logic.

Either renumber (3→5→6 becomes 3→4→5) or add a placeholder: 4. *(reserved)* with a brief note.

Fix this →


3. discover-prs.sh silently truncates at 200 PRs with no warning

File: plugins/source-control/skills/pull-request/scripts/discover-prs.sh

RAW="$(gh pr list --state open --limit 200 ...)"

On a repo with >200 open PRs, the babysit loop silently processes only the oldest 200. Since the response carries no "truncated" indicator visible to the filter, callers have no way to detect the cap was hit. The cap itself is reasonable, but a stderr notice when the result count equals the limit would make the behavior visible:

count=$(printf '%s' "$RAW" | jq 'length')
if [[ "$count" -ge 200 ]]; then
  printf 'discover-prs: result set hit the 200-PR limit; some PRs may be omitted\n' >&2
fi

Fix this →


4. Missing explanation for omitting -e in two scripts

Files:

fetch-all-pr-comments.sh helpfully documents why it uses set -uo pipefail without -e:

set -uo pipefail # -e omitted: gh api failures explicitly guarded with || { exit N }

The other two scripts use set -uo pipefail with no explanation. Future contributors may add -e expecting it to be an oversight, changing behavior. A one-line comment matching the fetch-all-pr-comments.sh convention would close this gap.


5. parse-branch-issue.sh case-sensitivity undocumented

File: plugins/source-control/skills/pull-request/scripts/parse-branch-issue.sh:22

if [[ "$BRANCH" =~ ^[a-z]+/(routine-issue-)?([0-9]+)- ]]; then

The [a-z]+ prefix matches only lowercase Conventional Commits types. Branches like Feature/123-foo or FEAT/123-foo won't yield an issue number, so gh pr create won't append Closes #N. This is fine for repos enforcing lowercase naming, but it's a silent no-op for others with no diagnostic. A brief note in the script header (# Note: type prefix must be lowercase) would prevent confusion during consumer onboarding.


Positive observations

  • Heredoc commit mechanic in commit/SKILL.md is exactly right: --cleanup=verbatim, single-quoted delimiter, surgical staging, no .git/<TEMP>.txt, with the PowerShell warning. This is the canonical pattern.
  • babysit-readiness-gate.sh counting logic correctly uses grep -o | grep -c . to count occurrences (not input lines), and the self_source_bodies exclusion of classification-table rows prevents phantom findings from inflating the finding count — a subtle correctness property well-commented.
  • Fork-safe checkout (gh pr checkout <N> vs bare git checkout) is enforced in the monitor checklist and babysit flow. This is the fix for a real class of fork-PR bugs.
  • The three-tier event delivery hierarchy (push channel → Monitor tool → gh polling) is correct in priority and properly guarded with the mandatory checklist that prevents jump-to-polling.
  • jq arg injection is cleanly avoided throughout by using --argjson/--arg flags rather than string interpolation into jq programs.
  • Test fixture isolation via --comments-json / --prs-json flags that exercise the exact same filter path as live fetches is a well-designed testing pattern.

Overall this is merge-ready after the scratch-dir leak (finding 1) is addressed. Findings 2–5 are documentation and usability polish that can be done in a fast follow if preferred.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale comment

Risk: medium. Cursor Bugbot did not complete successfully (check skipped — usage limit reached), so I am not approving. Human review is needed before merge; no reviewers were assigned because the only human repository contributor is the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb26d82655

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/source-control/skills/pull-request/reference/babysit.md Outdated
…gression test, dirty-tree guard on own-branch babysit path)

Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_b548953f-e3c6-431c-8b1f-012a13867ff8)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 4m 9s —— View job


PR Review: feat/publish-source-control

  • Gather context and read CLAUDE.md
  • Review round-8 fixes (plain P-num counting + dirty-tree guard)
  • Review shell scripts for correctness and security
  • Review skill files for alignment and accuracy
  • Check prior findings status
  • Post findings

Round-8 fixes: both verified correct

Fix 1 — Plain [P-num] severity counting (babysit-readiness-gate.sh)

SEVERITY_PLAIN_RE='\[P[0-9]\]' is correct. The ERE \[P[0-9]\] matches [P0][P9] literally. The comment at line 175–178 correctly explains why it can't double-count a Codex badge finding — the badge alt-text is ![PN Badge] (space before ]), so \[P[0-9]\] never matches it. The new count is summed into findings at line 226. The regression test at babysit-readiness-gate.test.sh:242 correctly asserts findings=2 for two [P1]/[P2] markers with only one classified.

One edge-case worth knowing: if a reviewer who uses the Codex shields-badge format also happens to write [P1] as a bracketed heading label in the same comment body, both the badge URL and the plain marker would be counted — yielding findings=2 for a single finding. This is a cosmetic over-count (makes the gate harder to pass, not softer), and the format is unusual enough to be a non-issue in practice.

Fix 2 — Dirty-tree guard on own-branch (babysit.md)

babysit.md:193-207 now correctly applies git status --porcelain and degrades to read-only even when CUR_BRANCH == BRANCH. The comment "uncommitted changes may be another session's WIP even on this branch" accurately states the invariant. ✓


Outstanding findings from prior rounds

These five were called out in the previous review and remain unaddressed in round-8 (the commit message is explicit that round-8 targeted the two Codex findings only).

1. Resource leak — scratch dir never cleaned up in fetch-failed-logs.sh (prior Finding 1)

Severity: moderate. When FETCH_LOGS_SCRATCH and CLAUDE_PLUGIN_DATA are both unset, SCRATCH=$(mktemp -d) at line 239 creates a temp dir that is never removed. The ZIP at $ZIP_PATH is deleted on line 396 when KEEP_ZIP=0, and $EXTRACT_DIR is cleaned by the trap cleanup_extract EXIT at line 308 — but $SCRATCH itself has no cleanup path.

The per-job path exits at line 275 (exit 0) with $out_path ($SCRATCH/job-${JOB_ID}-logs.txt) also uncleaned, and $SCRATCH still leaked.

In a plugin-installed context CLAUDE_PLUGIN_DATA will be set so real users are unaffected. The leak surfaces in ad-hoc invocations and in the test suite.

fetch-failed-logs.sh:233

Fix this →

2. Phase 0 smart-default list skips step 4 in SKILL.md (prior Finding 2)

SKILL.md:99 — the numbered list jumps 3 → 5 → 6. Step 4 is absent. Step 2a references "skip steps 3-6 entirely" which implies step 4 existed at some point. Renumber 5→4, 6→5 and update the "skip steps 3-6" reference to "skip steps 3-5".

Fix this →

3. discover-prs.sh silently truncates at 200 PRs (prior Finding 3)

discover-prs.sh:86gh pr list --limit 200 returns silently when the result count equals the cap. On repos with >200 open PRs, the babysit loop misses the newest PRs with no indication anything was dropped. A stderr notice when jq 'length' equals 200 closes this gap.

Fix this →

4. Missing -e omission comment in two scripts (prior Finding 4)

babysit-readiness-gate.sh:53 and fetch-annotations.sh:25 both use set -uo pipefail without explaining the -e omission, unlike fetch-all-pr-comments.sh:26 which documents it. Add the same comment pattern to both.

5. parse-branch-issue.sh case-sensitivity undocumented (prior Finding 5)

parse-branch-issue.sh:22^[a-z]+/ matches only lowercase type prefixes. Branches like Feature/123-foo silently produce no issue number and gh pr create won't append Closes #N. Add a header comment noting the lowercase requirement.


Summary

Round-8 is correct: the plain [P-num] counting fix is sound, the regression test is well-constructed, and the dirty-tree guard on own-branch is the right fix for the Codex P2. Five prior findings remain open. Finding 1 (scratch dir leak) is the only one with any runtime impact; findings 2–5 are documentation/usability polish that don't affect correctness.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk: medium. Cursor Bugbot did not complete successfully (check skipped), so I am not approving. Human review is needed before merge; no reviewers were assigned because the only human repository contributor is the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf90cfb332

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/source-control/skills/worktree/context/cleanup.md Outdated
kyle-sexton and others added 2 commits July 11, 2026 12:32
Co-Authored-By: Claude Fable 5 (1M context) <noreply@anthropic.com>
…ontrol

# Conflicts:
#	.claude-plugin/marketplace.json
#	README.md
@cursor

cursor Bot commented Jul 11, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_12b80ec7-8357-4f72-815c-49c30966865f)

@claude

claude Bot commented Jul 11, 2026

Copy link
Copy Markdown

Claude finished @kyle-sexton's task in 2m 15s —— View job


PR Review: feat/publish-source-control

  • Read changed files and gather context
  • Check status of 5 prior findings
  • Review new merge commit changes
  • Review shell scripts for correctness and security
  • Review skill files for alignment and accuracy
  • Post findings

Latest commit (b7fd0c7)

The head commit is a merge from origin/main that pulled in the new songwriting plugin (fab32a4). The only files changed in the source-control plugin were marketplace.json and README.md (conflict resolution). No source-control plugin behavior changed.

The preceding commit 8aa7ac9 (round-9 P1) fixed the dirty-worktree-before-force-removal finding from Codex.


Round-9 fix: verified correct

Codex P1 — Guard dirty worktrees before forcing removal (cleanup.md §4b)

cleanup.md:67 now contains an explicit escalation guard: when git worktree remove <path> fails, the procedure runs git -C <path> status --porcelain and git -C <path> log --branches --not --remotes --oneline | head to check for uncommitted edits and unpushed commits before allowing --force. If either check is non-empty, the skill surfaces the summary to the user and requires explicit per-worktree confirmation before forcing. This is the correct pattern — it prevents data loss without blocking legitimate cleanup of lock-only failures. ✓


Outstanding findings (5 prior, all still open)

1. Resource leak — scratch dir never cleaned up in fetch-failed-logs.sh

Severity: moderate. When both FETCH_LOGS_SCRATCH and CLAUDE_PLUGIN_DATA are unset, SCRATCH=$(mktemp -d) at line 238 creates a temp directory that is never removed. The existing traps clean $EXTRACT_DIR (line 308) and $ZIP_PATH when KEEP_ZIP=0 (line 396), but $SCRATCH itself has no cleanup path.

The per-job path at line 275 also exits with $out_path uncleaned when KEEP_ZIP=0.

In a plugin-installed context CLAUDE_PLUGIN_DATA will be set, so real users are unaffected. The leak surfaces in ad-hoc invocations and the test suite.

Fix: track whether $SCRATCH came from mktemp and add cleanup:

SCRATCH_IS_TEMP=0
if [[ -z "$SCRATCH" ]]; then
  if [[ -n "${CLAUDE_PLUGIN_DATA:-}" ]]; then
    SCRATCH="$CLAUDE_PLUGIN_DATA/scratch"
  else
    SCRATCH=$(mktemp -d)
    SCRATCH_IS_TEMP=1
  fi
fi

Then add [[ "$SCRATCH_IS_TEMP" -eq 1 && "$KEEP_ZIP" -eq 0 ]] && rm -rf "$SCRATCH" to the EXIT trap, and rm -f "$out_path" before the per-job exit 0 when KEEP_ZIP=0.

Fix this →


2. Phase 0 smart-default list skips step 4 in SKILL.md

SKILL.md:88–100 — the numbered list reads 1 → 2 → 3 → 5 → 6, with step 4 absent. Step 2a references "skip steps 3-6 entirely", implying step 4 existed. Renumber steps 5 and 6 to 4 and 5, and update the "skip steps 3-6" cross-reference in step 2a to "skip steps 3-5".

Fix this →


3. discover-prs.sh silently truncates at 200 PRs with no warning

discover-prs.sh:86gh pr list --limit 200 silently drops PRs beyond the cap. On repos with >200 open PRs, babysit processes only the oldest 200 with no indication that results were truncated. A stderr notice when the result count equals the cap closes the gap:

count=$(printf '%s' "$RAW" | jq 'length')
if [[ "$count" -ge 200 ]]; then
  printf 'discover-prs: result set hit the 200-PR limit; some PRs may be omitted\n' >&2
fi

Fix this →


4. Missing -e omission comment in two scripts

babysit-readiness-gate.sh:53 and fetch-annotations.sh:25 both use set -uo pipefail with no explanation of why -e is absent. fetch-all-pr-comments.sh:26 documents this correctly with # -e omitted: gh api failures explicitly guarded with || { exit N }. Future contributors may add -e as an apparent oversight, silently changing error-handling behavior. Add the same inline comment to both scripts.


5. parse-branch-issue.sh case-sensitivity undocumented

parse-branch-issue.sh:22 — the regex ^[a-z]+/ matches only lowercase Conventional Commits type prefixes. Branches like Feature/123-foo or FEAT/123-foo silently produce no issue number, so gh pr create won't append Closes #N. Add a header comment noting the lowercase requirement to prevent consumer confusion:

# Note: type prefix must be lowercase (e.g. feat/, fix/) — mixed-case branches yield no match.

Summary

Round-9 (dirty-worktree guard before --force) is correct and merged. The merge commit brings in only the unrelated songwriting plugin. Five prior findings remain open: finding 1 (scratch dir leak) has the only runtime impact; findings 2–5 are documentation and usability polish. This is merge-ready after finding 1 is addressed.

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Risk: medium. Cursor Bugbot did not complete successfully (check skipped — usage limit reached), so I am not approving. Human review is needed before merge; no reviewers were assigned because the only human repository contributor is the PR author.

Open in Web View Automation 

Sent by Cursor Approval Agent: Pull Request Router and Approver

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7fd0c7115

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/source-control/skills/pull-request/reference/create.md
Comment thread plugins/source-control/skills/pull-request/reference/babysit.md
Comment thread plugins/source-control/skills/pull-request/reference/merge.md
@kyle-sexton
kyle-sexton merged commit 776bdde into main Jul 11, 2026
22 checks passed
@kyle-sexton
kyle-sexton deleted the feat/publish-source-control branch July 11, 2026 16:44
kyle-sexton added a commit that referenced this pull request Jul 16, 2026
…ss lint (#203)

## Summary

Closes decisions #38, #71, #72 (Decisions Log:
https://claude.ai/code/artifact/232ecdce-8316-4880-8c0a-dc3c7dcf3a63).

- **#38** `formatting-create-md-attribution-footer-drift`: `create.md`'s
PR-body heredoc now emits the `🤖 Generated with Claude Code` attribution
footer it documents elsewhere but previously didn't actually emit.
- **#71** `naming-work-items-checklist-template-staleness`:
`templates/checklist.md`'s `add` action reconciled to `add.md`'s actual
current behavior — `--force` skip, `--type` native-Issue-Type resolution
(org repos) vs. `type:` label (personal/non-org repos), `--agent-ready`
body template, `--recurring` title prefix — none of which the checklist
previously mentioned.
- **#72** `tooling-gov-commit-skill-composition-lint`: new `guardrails`
plugin hook `flag-commit-pr-skill-bypass.sh` — advisory
`PreToolUse`/`Bash` guard that flags direct `git commit` (missing the
canonical `-F -` + `--trailer` shape) or any `gh pr create`, nudging
toward this marketplace's own `/commit` / `/pull-request create` skills.
Gated on the consuming project actually having `source-control` enabled
in its own `.claude/settings.json` (fails quiet on uncertain state, per
the plugin's existing advisory-guard posture). Mirrors
`block-hook-bypass.sh`'s literal-stripping detection and the shared
telemetry envelope.

## Verification

- New hook's own test suite: 19/19 passed.
- `shellcheck` on both the hook and its test — clean.
- `guardrails` version bumped 0.3.2 → 0.4.0 (new toggleable guard),
README's guard table/kill-switch table/consumer-seams section updated to
match.

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant