Skip to content

refactor(create-pr): improve quality, DRY code, strengthen tests - #580

Merged
baleen37 merged 11 commits into
mainfrom
autoresearch/create-pr-quality-2026-03-26
Mar 26, 2026
Merged

refactor(create-pr): improve quality, DRY code, strengthen tests#580
baleen37 merged 11 commits into
mainfrom
autoresearch/create-pr-quality-2026-03-26

Conversation

@baleen37

@baleen37 baleen37 commented Mar 26, 2026

Copy link
Copy Markdown
Owner

Summary

Improve create-pr skill quality: fix stderr routing, extract shared utilities to lib.sh, add recovery documentation, and strengthen test coverage.

Changes

  • Fix all error/failure messages to go to stderr (verify-pr-status, sync-with-base, wait-for-merge)
  • Create scripts/lib.sh with shared resolve_base_branch() and require_git_repo() functions, replacing 3x duplicated base branch detection and 2x duplicated git repo checks
  • Add Recovery section to SKILL.md documenting sync-with-base and verify-pr-status
  • Add 10 new BATS tests: 5 for lib.sh, 5 for sync-with-base (23 → 33 total)

Tests

  • All 33 BATS tests pass (bats tests/skills/test_create_pr_verify_status.bats)
  • All 63 project-wide tests pass (bats tests/)
  • ShellCheck 0 warnings across all scripts

Breaking

None

Summary by CodeRabbit

  • Documentation

    • Added recovery steps for handling pre-flight check failures with troubleshooting guidance.
    • Updated failure condition documentation for improved accuracy.
  • Tests

    • Expanded test coverage for utility functions and script validation.
  • Chores

    • Refactored shared utility functions to reduce code duplication.
    • Improved error output handling across scripts.

Test User added 10 commits March 26, 2026 11:56
…provement

Skill for improving a file (prompt, config, template) toward reference
quality through repeated single-change A/B testing. Each iteration makes
exactly one change, tests it against reference examples via parallel
generation + judge evaluation, and adopts only what works.

Key design decisions:
- One change per iteration (bundled changes hide what helped/hurt)
- Dynamic next-change based on judge feedback (not pre-planned list)
- Same inputs every iteration for valid comparison
- Adopt on TIE (change that doesn't hurt is worth keeping)
- Stop after 2+ consecutive rejections (rethink approach)
Replace eval-specific iterative-eval with a general-purpose iterate
skill. Works for any incremental improvement: prompts, code, configs,
docs — anything where you can verify whether a change helped.

Key design:
- One change per iteration (clear signal)
- Pluggable verification (test, build, judge, user, metric, composite)
- Feedback-driven next change (not pre-planned)
- Stop on 2+ consecutive rejections

BREAKING CHANGE: removes iterative-eval skill
Baseline: 90/100 — shellcheck 0, tests 100%, code_quality 15/25, skillmd 25/25
Result: {"status":"keep","quality_score":95,"code_quality":20}
New baseline: 93/100 with advanced quality checks
DRY: resolve_base_branch() replaces 3x duplicated detection logic

Result: {"status":"keep","quality_score":98,"advanced_quality":19}
…th-base tests

SKILL.md now documents sync-with-base and verify-pr-status recovery paths.
Added 5 new BATS tests for sync-with-base.sh.

Result: {"status":"keep","quality_score":100,"total_tests":28}
…ests

DRY: git-repo check now shared via require_git_repo().
Added 5 lib.sh tests (33 total).

Result: {"status":"keep","quality_score":100,"total_tests":33}
@baleen37
baleen37 enabled auto-merge (squash) March 26, 2026 03:16
@coderabbitai

coderabbitai Bot commented Mar 26, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@baleen37 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 19 minutes and 30 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 42cd055f-9ffc-4fbd-965f-64e58a15d7df

📥 Commits

Reviewing files that changed from the base of the PR and between 18f60c1 and 212ed20.

📒 Files selected for processing (1)
  • tests/me/me-specific.bats
📝 Walkthrough

Walkthrough

This pull request refactors the create-pr script suite by extracting shared utility functions (require_git_repo() and resolve_base_branch()) into a reusable lib.sh library, eliminating code duplication across multiple scripts. Error output streams are adjusted to stderr in several places, and documentation is enhanced with recovery procedures.

Changes

Cohort / File(s) Summary
Shared Utility Library
plugins/me/skills/create-pr/scripts/lib.sh
New library providing Git repo validation and base branch resolution helpers to be sourced by other scripts.
Create-PR Scripts
plugins/me/skills/create-pr/scripts/preflight-check.sh, sync-with-base.sh, verify-pr-status.sh, wait-for-merge.sh
Refactored to source and use shared lib.sh functions; replaced inline Git environment and branch resolution logic; redirected error/failure messages to stderr in several scripts.
Documentation
plugins/me/skills/create-pr/SKILL.md
Added Recovery section documenting manual steps for BEHIND/conflicts scenarios and clarified Stop Conditions for preflight check failures.
Tests
tests/skills/test_create_pr_verify_status.bats
Added lib.sh validation tests and sync-with-base.sh integration tests covering library function behavior and script sourcing.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A rabbit's refrain on shared code so fine,
Duplicates vanish in lib.sh's design,
Where functions once scattered now gather and blend,
And stderr flows right where errors should send!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: extracting shared functions (DRY code), improving error handling and documentation, and adding comprehensive tests.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch autoresearch/create-pr-quality-2026-03-26

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Test now recognizes both direct git rev-parse and shared require_git_repo.

@coderabbitai coderabbitai 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.

🧹 Nitpick comments (5)
tests/skills/test_create_pr_verify_status.bats (3)

26-33: Consider using teardown for temp directory cleanup.

If the test assertions fail, the rm -rf "$TEMP_DIR" line won't execute, leaving orphaned temp directories. Consider using BATS's teardown mechanism or a trap.

🧹 More robust cleanup pattern
 `@test` "lib.sh: require_git_repo exits 2 outside git repo" {
   TEMP_DIR=$(mktemp -d)
+  # Ensure cleanup on test exit
+  trap "rm -rf '$TEMP_DIR'" RETURN
   cd "$TEMP_DIR"
   run env -u GIT_DIR -u GIT_WORK_TREE bash -c "source '$LIB_SCRIPT' && require_git_repo"
   [ "$status" -eq 2 ]
   [[ "$output" =~ "Not in a git repository" ]]
-  rm -rf "$TEMP_DIR"
 }

Alternatively, consider storing temp dirs in a test-level variable and cleaning up in a shared teardown function.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/skills/test_create_pr_verify_status.bats` around lines 26 - 33, The
test "lib.sh: require_git_repo exits 2 outside git repo" currently removes
TEMP_DIR at the end of the test which will not run if assertions fail; replace
the inline rm -rf cleanup with a BATS teardown (or a shell trap) that removes
the TEMP_DIR after each test: create a teardown function (or add a trap) that
checks and deletes the TEMP_DIR variable set in the test before exiting, and
ensure the test still sets TEMP_DIR and calls require_git_repo so cleanup runs
regardless of assertion outcomes.

95-102: Same cleanup concern as lib.sh tests.

Apply the same trap pattern here for robust temp directory cleanup.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/skills/test_create_pr_verify_status.bats` around lines 95 - 102, The
test "sync-with-base.sh: exits 2 when not in a git repository" creates a
TEMP_DIR but doesn’t guarantee cleanup on failure; add the same trap pattern
used in lib.sh tests: after creating TEMP_DIR with TEMP_DIR=$(mktemp -d)
register a trap like trap 'rm -rf "$TEMP_DIR"' EXIT (or using a cleanup
function) so the directory is removed on test exit, then cd into "$TEMP_DIR" and
run the test using SYNC_SCRIPT; ensure you remove the explicit rm -rf
"$TEMP_DIR" at the end since the trap covers cleanup.

143-151: Test assertion may be fragile.

This test runs preflight-check.sh without a base branch argument outside a git repo. However, with the lib.sh integration, require_git_repo runs first (line 15 of preflight-check.sh) and exits with "Not in a git repository", not with a generic "ERROR" about the base branch. The test passes because [[ "$output" =~ "ERROR" ]] matches, but the description "exits 2 when no base branch given and gh fails" doesn't match the actual behavior being tested.

Consider updating the test name and assertion to match the actual behavior, or restructure to test base branch resolution separately (as done in lib.sh: resolve_base_branch tests).

📝 Suggested clarification
-@test "preflight-check.sh: exits 2 when no base branch given and gh fails" {
+@test "preflight-check.sh: exits 2 outside git repo (no args)" {
   PREFLIGHT_SCRIPT="${BATS_TEST_DIRNAME}/../../plugins/me/skills/create-pr/scripts/preflight-check.sh"
   TEMP_DIR=$(mktemp -d)
   cd "$TEMP_DIR"
   run env -u GIT_DIR -u GIT_WORK_TREE "$PREFLIGHT_SCRIPT"
   [ "$status" -eq 2 ]
-  [[ "$output" =~ "ERROR" ]]
+  [[ "$output" =~ "Not in a git repository" ]]
   rm -rf "$TEMP_DIR"
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/skills/test_create_pr_verify_status.bats` around lines 143 - 151, The
test "preflight-check.sh: exits 2 when no base branch given and gh fails" is
asserting a generic "ERROR" but actually triggers require_git_repo in
preflight-check.sh which prints "Not in a git repository"; either update the
test name and assertion to expect the repo-related behavior (change the test
title and assert output contains "Not in a git repository" and status 2), or
modify the test to run inside a git repo (git init in TEMP_DIR) so
preflight-check.sh proceeds to base-branch resolution and gh failure (to
exercise resolve_base_branch/lib.sh logic); reference preflight-check.sh and the
require_git_repo/resolve_base_branch behavior when making the change.
plugins/me/skills/create-pr/scripts/verify-pr-status.sh (1)

45-52: Minor inconsistency: blank line before error message goes to stdout.

Line 46 outputs a blank echo "" to stdout while the subsequent error messages go to stderr. This could cause interleaved output if stdout and stderr are directed to different destinations.

🔧 Suggested fix
     if [[ $FAILED_REQUIRED -gt 0 ]]; then
-      echo ""
+      echo "" >&2
       echo "✗ Required CI checks failed" >&2
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@plugins/me/skills/create-pr/scripts/verify-pr-status.sh` around lines 45 -
52, In verify-pr-status.sh the blank echo before the error block writes to
stdout while the rest of the error messages use stderr; change that blank echo
to redirect to stderr (use echo "" >&2) or remove it so all error-related output
for the FAILED_REQUIRED branch consistently goes to stderr; update the echo
invocation near the FAILED_REQUIRED check that precedes the "✗ Required CI
checks failed" and subsequent jq output.
plugins/me/skills/create-pr/SKILL.md (1)

51-61: Good addition of Recovery section.

The documentation clearly explains the recovery workflow for BEHIND/conflict scenarios.

Per static analysis hints, add blank lines around the fenced code blocks for better markdown compatibility.

📝 Markdown formatting fix
 ## Recovery

 If preflight-check reports BEHIND or conflicts, sync first:
+
 ```bash
 "${CLAUDE_PLUGIN_ROOT}/skills/create-pr/scripts/sync-with-base.sh"

To check PR status without modifying anything:
+

"${CLAUDE_PLUGIN_ROOT}/skills/create-pr/scripts/verify-pr-status.sh"
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @plugins/me/skills/create-pr/SKILL.md around lines 51 - 61, In SKILL.md, add
a blank line before and after each fenced code block to satisfy markdown
parsers: specifically surround the bash blocks that contain "${CLAUDE_PLUGIN_ROOT}/skills/create-pr/scripts/sync-with-base.sh" and "${CLAUDE_PLUGIN_ROOT}/skills/create-pr/scripts/verify-pr-status.sh" with an empty line above the opening bash and an empty line below the closing ``` so
both code blocks have blank lines separating them from the surrounding
paragraphs.


</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🤖 Prompt for all review comments with AI agents</summary>

Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In @plugins/me/skills/create-pr/scripts/verify-pr-status.sh:

  • Around line 45-52: In verify-pr-status.sh the blank echo before the error
    block writes to stdout while the rest of the error messages use stderr; change
    that blank echo to redirect to stderr (use echo "" >&2) or remove it so all
    error-related output for the FAILED_REQUIRED branch consistently goes to stderr;
    update the echo invocation near the FAILED_REQUIRED check that precedes the "✗
    Required CI checks failed" and subsequent jq output.

In @plugins/me/skills/create-pr/SKILL.md:

  • Around line 51-61: In SKILL.md, add a blank line before and after each fenced
    code block to satisfy markdown parsers: specifically surround the bash blocks that contain "${CLAUDE_PLUGIN_ROOT}/skills/create-pr/scripts/sync-with-base.sh" and "${CLAUDE_PLUGIN_ROOT}/skills/create-pr/scripts/verify-pr-status.sh" with an empty line above the opening bash and an empty line below the closing ``` so
    both code blocks have blank lines separating them from the surrounding
    paragraphs.

In @tests/skills/test_create_pr_verify_status.bats:

  • Around line 26-33: The test "lib.sh: require_git_repo exits 2 outside git
    repo" currently removes TEMP_DIR at the end of the test which will not run if
    assertions fail; replace the inline rm -rf cleanup with a BATS teardown (or a
    shell trap) that removes the TEMP_DIR after each test: create a teardown
    function (or add a trap) that checks and deletes the TEMP_DIR variable set in
    the test before exiting, and ensure the test still sets TEMP_DIR and calls
    require_git_repo so cleanup runs regardless of assertion outcomes.
  • Around line 95-102: The test "sync-with-base.sh: exits 2 when not in a git
    repository" creates a TEMP_DIR but doesn’t guarantee cleanup on failure; add the
    same trap pattern used in lib.sh tests: after creating TEMP_DIR with
    TEMP_DIR=$(mktemp -d) register a trap like trap 'rm -rf "$TEMP_DIR"' EXIT (or
    using a cleanup function) so the directory is removed on test exit, then cd into
    "$TEMP_DIR" and run the test using SYNC_SCRIPT; ensure you remove the explicit
    rm -rf "$TEMP_DIR" at the end since the trap covers cleanup.
  • Around line 143-151: The test "preflight-check.sh: exits 2 when no base branch
    given and gh fails" is asserting a generic "ERROR" but actually triggers
    require_git_repo in preflight-check.sh which prints "Not in a git repository";
    either update the test name and assertion to expect the repo-related behavior
    (change the test title and assert output contains "Not in a git repository" and
    status 2), or modify the test to run inside a git repo (git init in TEMP_DIR) so
    preflight-check.sh proceeds to base-branch resolution and gh failure (to
    exercise resolve_base_branch/lib.sh logic); reference preflight-check.sh and the
    require_git_repo/resolve_base_branch behavior when making the change.

</details>

---

<details>
<summary>ℹ️ Review info</summary>

<details>
<summary>⚙️ Run configuration</summary>

**Configuration used**: defaults

**Review profile**: CHILL

**Plan**: Pro

**Run ID**: `dfa691c5-65a1-4800-8511-e7e1b9e10f68`

</details>

<details>
<summary>📥 Commits</summary>

Reviewing files that changed from the base of the PR and between 2cf2983baba2ffc961397d95c7383684a05e9a5d and 18f60c1b6a05b6e91c8e735b4350c4897af32639.

</details>

<details>
<summary>📒 Files selected for processing (7)</summary>

* `plugins/me/skills/create-pr/SKILL.md`
* `plugins/me/skills/create-pr/scripts/lib.sh`
* `plugins/me/skills/create-pr/scripts/preflight-check.sh`
* `plugins/me/skills/create-pr/scripts/sync-with-base.sh`
* `plugins/me/skills/create-pr/scripts/verify-pr-status.sh`
* `plugins/me/skills/create-pr/scripts/wait-for-merge.sh`
* `tests/skills/test_create_pr_verify_status.bats`

</details>

</details>

<!-- This is an auto-generated comment by CodeRabbit for review status -->

@baleen37
baleen37 merged commit a018fb8 into main Mar 26, 2026
4 checks passed
@baleen37
baleen37 deleted the autoresearch/create-pr-quality-2026-03-26 branch March 26, 2026 03:20
baleen-release-app Bot pushed a commit that referenced this pull request Mar 26, 2026
## [16.0.1](v16.0.0...v16.0.1) (2026-03-26)

### Code Refactoring

* **create-pr:** improve quality, DRY code, strengthen tests ([#580](#580)) ([a018fb8](a018fb8))

### BREAKING CHANGES

* **create-pr:** removes iterative-eval skill

* chore(autoresearch): setup create-pr quality experiment

Baseline: 90/100 — shellcheck 0, tests 100%, code_quality 15/25, skillmd 25/25

* fix(create-pr): send all error/failure messages to stderr

Result: {"status":"keep","quality_score":95,"code_quality":20}

* chore(autoresearch): expand metrics with DRY, test depth, error recovery

New baseline: 93/100 with advanced quality checks

* refactor(create-pr): extract shared base branch detection to lib.sh

DRY: resolve_base_branch() replaces 3x duplicated detection logic

Result: {"status":"keep","quality_score":98,"advanced_quality":19}

* feat(create-pr): add recovery section to SKILL.md, strengthen sync-with-base tests

SKILL.md now documents sync-with-base and verify-pr-status recovery paths.
Added 5 new BATS tests for sync-with-base.sh.

Result: {"status":"keep","quality_score":100,"total_tests":28}

* refactor(create-pr): extract require_git_repo to lib.sh, add lib.sh tests

DRY: git-repo check now shared via require_git_repo().
Added 5 lib.sh tests (33 total).

Result: {"status":"keep","quality_score":100,"total_tests":33}

* docs(autoresearch): update dashboard, worklog, and what's-been-tried

* chore(create-pr): remove autoresearch scaffolding

* fix(tests): accept require_git_repo as valid git repo validation

Test now recognizes both direct git rev-parse and shared require_git_repo.
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