diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000..3fa6f43 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,42 @@ +name: Bug report +description: Something in devloop does not behave as documented. +labels: [bug] +body: + - type: textarea + id: what-happened + attributes: + label: What happened + description: What you ran and what went wrong. + placeholder: "devloop .specs/change.md exited 1 with ..." + validations: + required: true + - type: textarea + id: expected + attributes: + label: Expected behavior + validations: + required: true + - type: textarea + id: repro + attributes: + label: Steps to reproduce + description: A minimal sequence of commands. + render: shell + validations: + required: true + - type: textarea + id: env + attributes: + label: Environment + description: Output of `devloop --version` and `devloop doctor`, plus OS and shell. + render: shell + validations: + required: true + - type: textarea + id: logs + attributes: + label: Relevant logs + description: Paste run output. Redact anything sensitive. + render: shell + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000..ad3ec39 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Questions and ideas + url: https://github.com/satyaborg/devloop/discussions + about: Ask questions or discuss ideas before opening an issue. diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 0000000..e1dc36b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,24 @@ +name: Feature request +description: Suggest a change or addition to devloop. +labels: [enhancement] +body: + - type: textarea + id: problem + attributes: + label: Problem + description: The workflow or limitation that motivates this. + validations: + required: true + - type: textarea + id: proposal + attributes: + label: Proposed change + description: What devloop should do instead. + validations: + required: true + - type: textarea + id: alternatives + attributes: + label: Alternatives considered + validations: + required: false diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000..2038eed --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,24 @@ + + +## Problem + + + +## Approach + + + +## Test evidence + + + +``` +bash scripts/devloop_test.sh +``` + +## Checklist + +- [ ] Commits follow Conventional Commits (`feat:`, `fix:`, `chore:`) +- [ ] `bash scripts/devloop_test.sh` passes +- [ ] `shellcheck` is clean on changed scripts +- [ ] Updated `README.md` / `AGENTS.md` if user-facing behavior changed diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..cd87e96 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,52 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +permissions: + contents: read + +jobs: + test: + name: test (${{ matrix.os }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + steps: + - uses: actions/checkout@v4 + + - name: Configure git identity + run: | + git config --global user.name "devloop-ci" + git config --global user.email "ci@devloop.sh" + git config --global init.defaultBranch main + + - name: Syntax check + run: bash -n devloop scripts/install.sh scripts/release.sh scripts/skill_helpers.sh scripts/install.remote.sh scripts/devloop_test.sh + + - name: Test suite + run: bash scripts/devloop_test.sh + + - name: Version and help + run: | + ./devloop --version + ./devloop --help + + - name: Release dry run + run: ./scripts/release.sh patch --dry-run + + lint: + name: shellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Ensure shellcheck + run: command -v shellcheck >/dev/null 2>&1 || { sudo apt-get update && sudo apt-get install -y shellcheck; } + + - name: Run shellcheck + run: shellcheck devloop scripts/install.sh scripts/skill_helpers.sh scripts/release.sh scripts/install.remote.sh scripts/devloop_test.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index ba81188..054cfa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,3 +2,94 @@ All notable changes to this project will be documented in this file. +## [Unreleased] + +### Added + +- add compact status spinners ([12897cc](https://github.com/satyaborg/devloop/commit/12897ccfc25cc7d11f4778160b718df3673c8ac9)) +- pr-review-iterations ([d3bf74a](https://github.com/satyaborg/devloop/commit/d3bf74a89eeeba49feff01c5753ed68ee507cf49)) +- launch spec agents interactively ([f2bc531](https://github.com/satyaborg/devloop/commit/f2bc53123a16e65989bd665a8cbf3d172d06f0d0)) +- remote-installer ([06a0d77](https://github.com/satyaborg/devloop/commit/06a0d77a11a62d31587df38d3633e4921ec4fa4a)) +- add static marketing site ([2f29ceb](https://github.com/satyaborg/devloop/commit/2f29ceba72c1c60a0c1736d26a68a3dc7f4f2d37)) +- add why section and tighten install copy ([1ac6d9b](https://github.com/satyaborg/devloop/commit/1ac6d9be6b7f023631e97b8e80df9605de130e8c)) +- redesign marketing page to single-column layout ([b18f22d](https://github.com/satyaborg/devloop/commit/b18f22d83d1ed9a671b5ac67b163197210d00661)) +- add blog link, pointer cursor on links, drop FAQ dividers ([00ab55b](https://github.com/satyaborg/devloop/commit/00ab55b081cb7f99c2c578fc096b4db33fdf7568)) +- add when-(not)-to-use section and author attribution ([2aa69a2](https://github.com/satyaborg/devloop/commit/2aa69a2a9033a9616edaf131c8f8c7b21184734d)) +- sharpen FAQ copy and surface the verify hook ([b2e52ae](https://github.com/satyaborg/devloop/commit/b2e52ae3efb13eeff99a46b93303721598556b46)) +- switch marketing site font to JetBrains Mono ([3fb7e0a](https://github.com/satyaborg/devloop/commit/3fb7e0a9b1d90291fc58b9bf32ee6a3bc6585677)) +- use devloop artifacts in menu flow ([ecd2923](https://github.com/satyaborg/devloop/commit/ecd292388e6e129afe21f2f288c926159de741f3)) + + +### Breaking changes + +- add global devloop config defaults ([fe8cd53](https://github.com/satyaborg/devloop/commit/fe8cd53631f966110f388b2a013f25699f80e71b)) +- require devloop dependencies ([45ff96c](https://github.com/satyaborg/devloop/commit/45ff96c9a885b3ace7fefb860a6d05319c13d142)) + + +### Fixed + +- improve tui back navigation ([73b40a7](https://github.com/satyaborg/devloop/commit/73b40a7665b6da06b49d13c1e071d2adce3b52f7)) +- clarify pr mode docs ([cda2477](https://github.com/satyaborg/devloop/commit/cda2477d38e0a4886c300d56a4f2c24b6629fd6e)) +- remove dead spec generation path ([46fa3bc](https://github.com/satyaborg/devloop/commit/46fa3bc0bc4d8a24f208c20fffd89cabad06b055)) +- remote-installer ([71a3a16](https://github.com/satyaborg/devloop/commit/71a3a164b426249849dfe7b3ff459cacd54cc493)) +- populate-draft-pr-body ([6195115](https://github.com/satyaborg/devloop/commit/61951157980550584d14cbb558ed218664b6ff3a)) +- de-localize public PR surfaces ([5bb0986](https://github.com/satyaborg/devloop/commit/5bb09867cf896b2614520edfdceb14fcb3cdc162)) +- correct grammar and tighten marketing copy ([9b64fcc](https://github.com/satyaborg/devloop/commit/9b64fccfa4b14d1e1289c423c7ee974aeaf87a22)) +- render when-section markers as inline SVG and hide decorative markers from screen readers ([0caed06](https://github.com/satyaborg/devloop/commit/0caed06d9a8b408614ac60304cff1e6fdb97f944)) + +## [0.2.0](https://github.com/satyaborg/devloop/releases/tag/v0.2.0) - 2026-05-30 + +### Added + +- initial implementation ([96901ee](https://github.com/satyaborg/devloop/commit/96901ee67cbe8e01e4fe25cea9807d100dc94f59)) +- reuse agent sessions in devloop ([6cf72c5](https://github.com/satyaborg/devloop/commit/6cf72c59df7acf8ae95e66e882e7e05898365abd)) +- port devloop to bun opentui ([38cf9bd](https://github.com/satyaborg/devloop/commit/38cf9bde799ec7e8c5b47b261e0ff986a14dd67f)) +- show default cli welcome ([4e55181](https://github.com/satyaborg/devloop/commit/4e551816a2446ac041100b22c988eaa0e3e5a398)) +- run devloop in isolated worktrees ([17b7fd5](https://github.com/satyaborg/devloop/commit/17b7fd5ac76ee90feb601efd11ac4b902bd73c99)) +- derive semantic work names ([0bb4bf0](https://github.com/satyaborg/devloop/commit/0bb4bf0411c854f872038c0ca22826582dd65b40)) +- show tui step progress ([fcfe52a](https://github.com/satyaborg/devloop/commit/fcfe52af09db5c6b6d3dbecb3e170a9849a860ac)) +- bundle spec generation skill ([a4ae43d](https://github.com/satyaborg/devloop/commit/a4ae43d45cb9e8e3cbfb01ebde03e94bf67fd3a2)) +- configure coder and reviewer agents ([f00c2ae](https://github.com/satyaborg/devloop/commit/f00c2aee76b55f15a98c806e20a527c0062420f5)) +- require evidence-rich review matrices ([1f31f70](https://github.com/satyaborg/devloop/commit/1f31f7077da79fcca2ec1219252c3d0e7ce37373)) +- automate pass commits and prs ([4c222a7](https://github.com/satyaborg/devloop/commit/4c222a72eaa73535777ed0dfbe789902f704589b)) +- npm-release-readiness ([057aef0](https://github.com/satyaborg/devloop/commit/057aef0fc8e715952c394af4be8ba3fc6ba59b1d)) +- force maximum agent effort ([51af634](https://github.com/satyaborg/devloop/commit/51af634d573774b6a88d722927f3460c4081d854)) +- add bash devloop runtime ([f6611e0](https://github.com/satyaborg/devloop/commit/f6611e00c480058014b73708ab7bfdae6eefc5cc)) +- add adversarial review gates ([5143efd](https://github.com/satyaborg/devloop/commit/5143efd46713e0b95b6e550d9e702fb2a814fba5)) +- overhaul interactive cli ui ([3d0f033](https://github.com/satyaborg/devloop/commit/3d0f0332592b1a68a4e3606249ca82013b7ba506)) +- configure spec directories ([c8a7cbd](https://github.com/satyaborg/devloop/commit/c8a7cbdc1ee272f8baae9e146a180d271d55de94)) +- add scoped devloop config ([00868e6](https://github.com/satyaborg/devloop/commit/00868e6532e87e1663340c187bee34872a2db38e)) +- simplify spec path settings ([1e1213c](https://github.com/satyaborg/devloop/commit/1e1213cafabe8f984e45ee8212e3585bd768d15f)) +- polish interactive tui ([a4485ae](https://github.com/satyaborg/devloop/commit/a4485ae3022a827275bed4870128a6ebeda2ff2c)) +- add release versioning ([30c7297](https://github.com/satyaborg/devloop/commit/30c72976c1ac89e09788e799dac3aa4571871203)) +- harden devloop validation loop ([56bd2d5](https://github.com/satyaborg/devloop/commit/56bd2d56026ec94c179cde22fe6f0debeae307b7)) + + +### Breaking changes + +- install skills for codex and claude ([eb2cb6d](https://github.com/satyaborg/devloop/commit/eb2cb6de9f988ea2acac988f7f1fb782a25a39ba)) + + +### Documentation + +- add repository guidelines ([447dd0c](https://github.com/satyaborg/devloop/commit/447dd0ce63264b1fc9cc124eaa975fa179ee3e76)) +- link claude guide to agents ([70be06e](https://github.com/satyaborg/devloop/commit/70be06eebb326baaa54ff5eb4d8c6199f074d029)) +- clarify worktree cleanup ([3dc7b1b](https://github.com/satyaborg/devloop/commit/3dc7b1b239684e17683c04f8e0f3ba15c2d16b0e)) +- add license section ([ac82872](https://github.com/satyaborg/devloop/commit/ac8287290a2f7dae956248fc46411e9ac9cacf8b)) + + +### Fixed + +- surface devloop commit failures ([493031a](https://github.com/satyaborg/devloop/commit/493031ab90ba593ad2bc904ec3d8c0ba1fd92b96)) +- clarify worktree outputs ([6e1067a](https://github.com/satyaborg/devloop/commit/6e1067acf5cf0298a3e3c825176f190cbb346bbb)) +- clean up naming temp logs ([424a502](https://github.com/satyaborg/devloop/commit/424a502fe78441e6b9e9877f719bc876acbd2210)) +- align tui navigation labels ([3f74b90](https://github.com/satyaborg/devloop/commit/3f74b90b0d87294c5224f33888f6c05346ba1397)) +- derive report subtitles from specs ([1984ca6](https://github.com/satyaborg/devloop/commit/1984ca6b8e82dfdd3689df864fc1108d38ec2517)) +- add topical report haiku ([2cd843d](https://github.com/satyaborg/devloop/commit/2cd843df292217f676e59b3631d7f6d922d3a1db)) +- key sessions by configured agent ([16ef419](https://github.com/satyaborg/devloop/commit/16ef419de2429bc4569fc7789fb4fb1998aefc0f)) +- align release readiness tests ([8d9f0bf](https://github.com/satyaborg/devloop/commit/8d9f0bf14d5ca4be0096e01cca8ca19d140f270b)) +- harden bash runtime helpers ([7fb28cc](https://github.com/satyaborg/devloop/commit/7fb28cc7f7da3788d7ef3a233242465ad4a8e2c9)) +- preserve interactive run status ([48cadbb](https://github.com/satyaborg/devloop/commit/48cadbb140662919f6ae8ce6597274cf755d13a1)) +- compute release bumps ([167b903](https://github.com/satyaborg/devloop/commit/167b903c58b5fbbc2658136e13eb42214cab54f2)) +- classify clean devloop worktrees ([546a59b](https://github.com/satyaborg/devloop/commit/546a59bac144e061a61d671770c7209a6dd4a76c)) + diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..44e768b --- /dev/null +++ b/CODE_OF_CONDUCT.md @@ -0,0 +1,14 @@ +# Code of Conduct + +This project adopts the [Contributor Covenant](https://www.contributor-covenant.org/), version 2.1. + +The full text is available at: +https://www.contributor-covenant.org/version/2/1/code_of_conduct/ + +In short: we are committed to a welcoming, harassment-free experience for everyone, regardless of background or identity. Be respectful and constructive in all project spaces. + +## Reporting + +Report unacceptable behavior to the maintainer at **satya.borg@gmail.com**. All reports are reviewed and handled confidentially. Maintainers are responsible for enforcement and may remove, edit, or reject contributions that violate this Code of Conduct. + +Enforcement follows the Contributor Covenant's [enforcement guidelines](https://www.contributor-covenant.org/version/2/1/code_of_conduct/#enforcement-guidelines). diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..b1d5bcc --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,53 @@ +# Contributing to devloop + +Thanks for your interest in improving devloop. This is a single-file Bash CLI with a fixture-style shell test suite. Changes stay small, regression-first, and self-documenting. + +## Getting set up + +```sh +git clone https://github.com/satyaborg/devloop.git +cd devloop +./scripts/install.sh # symlinks the checkout, installs gum/fzf and bundled skills +devloop doctor # verify required dependencies +``` + +Required to run a loop: Bash, git, `gum`, `fzf`, and the `codex` and `claude` CLIs. The test suite itself needs only Bash, git, and coreutils, so you can develop and test without the agent CLIs installed. + +## Development loop + +Run the same gates CI runs before opening a PR: + +```sh +bash -n devloop scripts/install.sh scripts/release.sh scripts/skill_helpers.sh scripts/install.remote.sh scripts/devloop_test.sh +shellcheck devloop scripts/install.sh scripts/skill_helpers.sh scripts/release.sh scripts/install.remote.sh scripts/devloop_test.sh +bash scripts/devloop_test.sh +``` + +The shell suite enforces 100% project function coverage for `devloop`, `scripts/skill_helpers.sh`, and `scripts/release.sh`. New functions need new tests. Keep tests fixture-style: assert generated files, git state, status codes, and user-visible output. + +## Coding style + +- Readable Bash with small named functions, quoted expansions, and explicit status handling. +- Portable across macOS and Linux shell utilities. +- Self-documenting code over inline comments. +- kebab-case for branch and spec slugs (`devloop/change`). + +## Commits and pull requests + +- Branch names: `type/short-description` (`feat/pr-mode`, `fix/null-check`). +- [Conventional Commits](https://www.conventionalcommits.org/) with three prefixes: `feat:`, `fix:`, `chore:`. Append `!` for breaking changes (`feat!:`). The changelog is generated from this history, so subjects matter. +- One logical change per commit. Keep PRs small and focused; a PR over ~300 LOC should probably be split. +- PRs include a short problem summary, the approach, and test evidence (`bash scripts/devloop_test.sh`). +- Update `README.md` and `AGENTS.md` when user-facing behavior changes. + +See [AGENTS.md](AGENTS.md) for the repository map and the same guidelines in agent-facing form. + +## Releases + +Releases are cut by maintainers with [`scripts/release.sh`](scripts/release.sh), which bumps `VERSION`, regenerates `CHANGELOG.md` from commit history with [git-cliff](https://git-cliff.org/), tags, and publishes the GitHub Release. You do not need to touch `VERSION` or `CHANGELOG.md` in a normal PR. + +## Reporting bugs and proposing features + +Open an issue using the templates. Security issues follow [SECURITY.md](SECURITY.md) instead of the public tracker. + +By contributing, you agree your contributions are licensed under the [MIT License](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..655efb0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,22 @@ +# Security Policy + +## Supported versions + +devloop is pre-1.0. Security fixes land on the latest released `0.x` version. Always update to the newest release before reporting. + +## Reporting a vulnerability + +Please report security issues privately. Do not open a public issue. + +- Preferred: open a [private security advisory](https://github.com/satyaborg/devloop/security/advisories/new) on this repository. +- Alternatively: email **satya.borg@gmail.com** with a description and reproduction steps. + +You can expect an initial response within a few days. Once a fix is available, we will publish a release and credit you unless you prefer to remain anonymous. + +## Scope and threat model + +devloop runs local agent CLIs (Codex, Claude Code) against your checkout. Those agents inherit your local credentials, `PATH`, and machine access. devloop adds no telemetry and sends no data anywhere on its own; network behavior depends entirely on the agents and commands you configure. + +If present, `.devloop/verify` is executed from the run worktree with the pass number and slug as arguments. Treat that script, and any spec you run, as code you are choosing to execute. Keep them local and auditable. + +Reports most relevant to devloop itself include: command injection in the runtime, unsafe handling of untrusted spec or config input, the remote installer (`scripts/install.remote.sh`) fetching or executing unverified content, and checksum-verification bypasses. diff --git a/devloop b/devloop index def18d5..d9ea982 100755 --- a/devloop +++ b/devloop @@ -2656,7 +2656,7 @@ frontmatter_value() { } ' | awk ' $0 == "" || $0 == "null" || $0 == "undefined" { next } - /^\<.*\>$/ { next } + /^<.*>$/ { next } /\|/ { next } { print } ' @@ -3143,7 +3143,9 @@ run_compact_command() { ''|*[!0-9]*) RUN_CODE=1 ;; esac RUN_OUTPUT="$(cat "$output_file")" + # shellcheck disable=SC2034 # RUN_STDOUT/RUN_STDERR round out the RUN_* result interface RUN_STDOUT="$RUN_OUTPUT" + # shellcheck disable=SC2034 RUN_STDERR="" rm -f "$output_file" "$code_file" [ "$RUN_CODE" -eq 0 ] diff --git a/scripts/devloop_test.sh b/scripts/devloop_test.sh index cc1963b..c14963d 100755 --- a/scripts/devloop_test.sh +++ b/scripts/devloop_test.sh @@ -1,5 +1,5 @@ #!/usr/bin/env bash -# shellcheck disable=SC2030,SC2031 +# shellcheck disable=SC2030,SC2031,SC2034,SC2317,SC2329 set -euo pipefail REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd) @@ -900,7 +900,20 @@ mkdir -p "$no_gh_bin" printf '#!/usr/bin/env bash\nexit 0\n' > "$no_gh_bin/codex" printf '#!/usr/bin/env bash\nexit 0\n' > "$no_gh_bin/claude" chmod +x "$no_gh_bin/codex" "$no_gh_bin/claude" -doctor_no_gh_output="$(HOME="$install_home" PATH="$bin_dir:$tool_bin:$no_gh_bin:/usr/bin:/bin" "$bin_dir/devloop" doctor 2>&1)" || fail "doctor failed when gh was unavailable" +# Mirror the system bin dirs without gh so `command -v gh` fails regardless of +# where gh is installed on the host (CI runners ship gh in /usr/bin). +sys_clean="$work/sys-clean" +mkdir -p "$sys_clean" +for sys_dir in /usr/bin /bin; do + [ -d "$sys_dir" ] || continue + for sys_entry in "$sys_dir"/*; do + sys_name="$(basename "$sys_entry")" + [ "$sys_name" = "gh" ] && continue + [ -e "$sys_clean/$sys_name" ] && continue + ln -s "$sys_entry" "$sys_clean/$sys_name" + done +done +doctor_no_gh_output="$(HOME="$install_home" PATH="$bin_dir:$tool_bin:$no_gh_bin:$sys_clean" "$bin_dir/devloop" doctor 2>&1)" || fail "doctor failed when gh was unavailable" contains "$doctor_no_gh_output" "devloop doctor: ready" "doctor no gh" contains "$doctor_no_gh_output" "[FAIL] gh installed" "doctor no gh" contains "$doctor_no_gh_output" "PR-backed loop readiness unavailable" "doctor no gh" @@ -1072,7 +1085,7 @@ contains "$(HOME="$helper_home" devloop_skills_dirs)" "$helper_home/.agents/skil devloop_can_replace_skill "$helper_home/.agents/skills/devloop-spec" || fail "installed skill should be replaceable" devloop_valid_skill_name "devloop-spec" || fail "valid skill name rejected" equals "$(devloop_skill_name "$helper_home/.agents/skills/devloop-spec/SKILL.md")" "devloop-spec" "skill name" -helper_doctor_output="$(HOME="$helper_home" PATH="$fake_bin:$PATH" devloop_doctor "$REPO_ROOT" 2>&1)" || fail "direct doctor failed" +helper_doctor_output="$(HOME="$helper_home" PATH="$fake_bin:$bin_dir:$tool_bin:$sys_clean" devloop_doctor "$REPO_ROOT" 2>&1)" || fail "direct doctor failed" contains "$helper_doctor_output" "devloop doctor: ready" "direct doctor" ok "direct skill helpers" @@ -1237,7 +1250,7 @@ add_origin_remote "$preflight_pr_repo" "$work/preflight-pr-remote.git" old_home="$HOME" old_path="$PATH" HOME="$install_home" -PATH="$no_gh_bin:$bin_dir:$tool_bin:/usr/bin:/bin" +PATH="$no_gh_bin:$bin_dir:$tool_bin:$sys_clean" export HOME PATH if preflight_run "$preflight_pr_repo" codex claude true >/dev/null 2>&1; then fail "PR preflight accepted missing gh"; fi contains "$PREFLIGHT_ERROR" "missing command: gh" "PR preflight missing gh" @@ -1272,7 +1285,7 @@ PATH="$fake_bin:$bin_dir:$tool_bin:$PATH" USE_TUI=false export HOME PATH equals "$(cd "$interactive_pr_repo" && interactive_create_pr_choice "$interactive_pr_repo")" "true" "interactive PR prompt defaults yes when ready" -PATH="$no_gh_bin:$bin_dir:$tool_bin:/usr/bin:/bin" +PATH="$no_gh_bin:$bin_dir:$tool_bin:$sys_clean" equals "$(cd "$interactive_pr_repo" && interactive_create_pr_choice "$interactive_pr_repo")" "false" "interactive PR prompt falls back local-only when unavailable" PATH="$old_path" HOME="$old_home"