From 1ab2c65c8e786c4b1ad1cfc2c6b98d4375a3dc13 Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 10:43:14 +1000
Subject: [PATCH 1/8] chore: silence benign shellcheck warnings

Annotate the RUN_* result-interface assignments (SC2034) and extend the test suite's disable list (SC2034/SC2329) so shellcheck passes at full strictness, matching the documented dev gate.
---
 devloop                 | 2 ++
 scripts/devloop_test.sh | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/devloop b/devloop
index def18d5..bda3e4f 100755
--- a/devloop
+++ b/devloop
@@ -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..879561a 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,SC2329
 set -euo pipefail
 
 REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)

From 6542a7fe983ec2323f4ba7c92a47c5e35039a40a Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 10:43:14 +1000
Subject: [PATCH 2/8] chore: add CI workflow

Run bash syntax check, the shell test suite, version/help, and a release dry-run on ubuntu and macOS, plus shellcheck lint.
---
 .github/workflows/ci.yml | 52 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 52 insertions(+)
 create mode 100644 .github/workflows/ci.yml

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

From 7ce2fe5c91eece52fdb869f39b694fecfa2cd229 Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 10:43:14 +1000
Subject: [PATCH 3/8] chore: add OSS community health files

Add CONTRIBUTING, CODE_OF_CONDUCT (Contributor Covenant 2.1), SECURITY, a PR template, and bug/feature issue forms.
---
 .github/ISSUE_TEMPLATE/bug_report.yml      | 42 +++++++++++++++++
 .github/ISSUE_TEMPLATE/config.yml          |  5 ++
 .github/ISSUE_TEMPLATE/feature_request.yml | 24 ++++++++++
 .github/PULL_REQUEST_TEMPLATE.md           | 24 ++++++++++
 CODE_OF_CONDUCT.md                         | 14 ++++++
 CONTRIBUTING.md                            | 53 ++++++++++++++++++++++
 SECURITY.md                                | 22 +++++++++
 7 files changed, 184 insertions(+)
 create mode 100644 .github/ISSUE_TEMPLATE/bug_report.yml
 create mode 100644 .github/ISSUE_TEMPLATE/config.yml
 create mode 100644 .github/ISSUE_TEMPLATE/feature_request.yml
 create mode 100644 .github/PULL_REQUEST_TEMPLATE.md
 create mode 100644 CODE_OF_CONDUCT.md
 create mode 100644 CONTRIBUTING.md
 create mode 100644 SECURITY.md

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 @@
+<!-- Keep PRs small and focused: one logical change. PRs over ~300 LOC should probably be split. -->
+
+## Problem
+
+<!-- What is broken or missing, and why it matters. -->
+
+## Approach
+
+<!-- How this change solves it. Note any tradeoffs. -->
+
+## Test evidence
+
+<!-- Paste the relevant output. -->
+
+```
+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/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.

From 851b248e2781ab461c2287faff6ba42fbdf5dffb Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 10:43:14 +1000
Subject: [PATCH 4/8] chore: seed changelog from commit history

Generate CHANGELOG.md with git-cliff so the changelog is populated ahead of the next release regeneration.
---
 CHANGELOG.md | 91 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

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))
+

From 06eee6703c8d9e59334b24aed68a2f04dda45e23 Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 10:50:41 +1000
Subject: [PATCH 5/8] fix: parse frontmatter portably across awk
 implementations

The placeholder-skip rule used \< \> which GNU awk treats as word boundaries, so quoted frontmatter values like "Chat Retry" were dropped to empty on gawk/mawk runners. Use literal angle brackets so the rule skips only <placeholder> lines on BSD awk, gawk, and mawk alike.
---
 devloop | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/devloop b/devloop
index bda3e4f..d9ea982 100755
--- a/devloop
+++ b/devloop
@@ -2656,7 +2656,7 @@ frontmatter_value() {
     }
   ' | awk '
     $0 == "" || $0 == "null" || $0 == "undefined" { next }
-    /^\<.*\>$/ { next }
+    /^<.*>$/ { next }
     /\|/ { next }
     { print }
   '

From 28b818f49d23bad08bab390de728fcf3df32d914 Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 10:50:41 +1000
Subject: [PATCH 6/8] chore: silence SC2317 in test stubs

Older shellcheck versions on CI report unreachable-command (SC2317) for indirectly-invoked test stubs where newer versions report SC2329. Disable both so lint passes regardless of shellcheck version.
---
 scripts/devloop_test.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/devloop_test.sh b/scripts/devloop_test.sh
index 879561a..f0f0af1 100755
--- a/scripts/devloop_test.sh
+++ b/scripts/devloop_test.sh
@@ -1,5 +1,5 @@
 #!/usr/bin/env bash
-# shellcheck disable=SC2030,SC2031,SC2034,SC2329
+# shellcheck disable=SC2030,SC2031,SC2034,SC2317,SC2329
 set -euo pipefail
 
 REPO_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)

From fadde5fd34a62c4de930f92f480a0a40c985ca76 Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 11:42:52 +1000
Subject: [PATCH 7/8] fix: make doctor/preflight gh-absence tests hermetic

The gh-missing assertions appended raw /usr/bin:/bin to PATH, so on CI runners that ship gh in /usr/bin the tests saw gh present and failed. Mirror the system bin dirs into a sanitized dir that excludes gh, so command -v gh fails regardless of host gh location.
---
 scripts/devloop_test.sh | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/scripts/devloop_test.sh b/scripts/devloop_test.sh
index f0f0af1..bbf39f5 100755
--- a/scripts/devloop_test.sh
+++ b/scripts/devloop_test.sh
@@ -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"
@@ -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"

From 9b9d7dbf546aa82e3656f89934712c90e2821d91 Mon Sep 17 00:00:00 2001
From: satyaborg <satya.borg@gmail.com>
Date: Tue, 9 Jun 2026 11:50:54 +1000
Subject: [PATCH 8/8] fix: make direct doctor test independent of ambient PATH

The direct devloop_doctor test relied on the ambient PATH supplying devloop, gum, and fzf, which only happens on a provisioned dev machine. On CI those are absent, so doctor reported not-ready. Supply all required deps via the controlled stub dirs (bin_dir, tool_bin) and sanitized system bin.
---
 scripts/devloop_test.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/devloop_test.sh b/scripts/devloop_test.sh
index bbf39f5..c14963d 100755
--- a/scripts/devloop_test.sh
+++ b/scripts/devloop_test.sh
@@ -1085,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"
 
