Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d87c6d8
docs: say plainly that --issues picks a destination and --scan-only s…
atomantic Aug 12, 2026
d091ffe
fix([issue-134]): assert review-fix commits are pushed before opening…
atomantic Aug 12, 2026
ef0ecf8
docs([issue-134]): log issue #134 to changelog
atomantic Aug 12, 2026
a11eb49
address self-review: fix stale step reference, ~opt contract, and cha…
atomantic Aug 12, 2026
b4e0a74
address review (claude): scope push assertion to the pass, use an exp…
atomantic Aug 12, 2026
4d7b525
address review (claude): derive the push target from @{u}, not the lo…
atomantic Aug 12, 2026
3ccec0a
address review (claude): derive the push target from config, and push…
atomantic Aug 12, 2026
1d029cb
address review (ollama): make the merge gate fail closed and the clea…
atomantic Aug 12, 2026
c68b15a
address review (claude): abort a conflicted retry rebase instead of s…
atomantic Aug 12, 2026
6645cb8
address review (claude): anchor the rebase-abort assertion to the els…
atomantic Aug 12, 2026
00e9b37
fix: guard possibly-empty array expansions so bash 3.2 can't fake a r…
atomantic Aug 12, 2026
57a5531
docs: say that --issues picks a destination, not a run mode, in simpl…
atomantic Aug 12, 2026
f6e59dd
address review (antigravity): gate the merge claim on --review-with a…
atomantic Aug 12, 2026
014712c
Merge pull request #140 from atomantic/claim/issue-135
atomantic Aug 12, 2026
bf2ff35
Merge pull request #136 from atomantic/docs/clarify-issues-flag-seman…
atomantic Aug 12, 2026
65db11f
chore: release v3.27.1
atomantic Aug 12, 2026
18b8901
address review (claude): commit gate fixes, derive do:pr's push targe…
atomantic Aug 13, 2026
8e1b68a
address review (claude): restore the local-upstream guard I dropped, …
atomantic Aug 13, 2026
0845542
address review (claude): key do:pr's push case split on the remote va…
atomantic Aug 13, 2026
1cbc601
address review (claude): pin the -u prohibition on the second push ca…
atomantic Aug 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions .changelogs/v3.27.1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Release v3.27.1

Released: 2026-08-12

## Highlights

- **Review fixes can no longer be silently left on your machine.** The review loop now pushes its own fix commits, `/do:pr` pushes anything still outstanding before opening a PR, and it refuses to merge while your branch is ahead of the remote — naming the commits that would have been dropped.
- **`--issues` reads as what it is: a destination, not a run mode.** `/do:simplify` and `/do:config` now say outright that the flag selects where findings are *recorded* and does not suppress remediation, and point at `--scan-only --issues` for the audit-and-file run people were actually reaching for.
- **Reviewer status reporting is more honest under bash 3.2** — an empty array expansion can no longer masquerade as a reviewer CLI error.

## Fixed
- **[issue-134] Review fixes are asserted pushed before a PR is opened or merged.** If a reviewer's fixes were committed but never pushed, every reviewer would report clean and CI would pass against the older pushed code while the fixes stayed local. The review loop now pushes them itself, `/do:pr` pushes anything outstanding before opening the PR, and the merge gate fails closed when the local branch is ahead of its upstream, listing the commits at risk.
- **A conflicted retry rebase is aborted instead of stranding the branch**, and the push target is derived from the tracking ref (`@{u}`) and config rather than assuming the local branch name matches the remote.
- **Possibly-empty array expansions are guarded** so bash 3.2 can't report a spurious reviewer `cli-error`. (#139)

## Docs
- **[issue-135] `--issues` no longer reads like it stops the run.** `/do:simplify`'s flag list and `/do:config`'s issue-mode default now state that `--issues` selects where findings are recorded and does not suppress remediation, and reference `--scan-only --issues` for the audit-and-file workflow. (#135, #136)
- **The merge claim is gated on `--review-with` and scoped to the pipeline commands**, so commands that never run a reviewer no longer imply one gates their merge.

## Full Changelog

**Full Diff**: https://github.com/atomantic/slashdo/compare/v3.27.0...v3.27.1
8 changes: 5 additions & 3 deletions commands/do/better-swift.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Run the full DevSecOps lifecycle optimized for Swift/SwiftUI multi-platform proj

Parse `$ARGUMENTS` for:
- **`--interactive`**: pause at each decision point for user approval
- **`--scan-only`**: run Phase 0 + 1 + 2 only (audit and plan), skip remediation
- **`--scan-only`**: run Phase 0 + 1 + 2 only (audit and plan), skip remediation — no worktree, no code changes, no PRs. **When `ISSUE_MODE` is also true, this is the "audit and file the work, don't touch my code" combination**: every surviving finding is filed as a labelled tracker issue before the run exits, not just the deferred subset (see the Phase 2 gate). `--scan-only` is the flag that stops the pipeline; `--issues` only chooses where findings are recorded
- **`--no-merge`**: run through PR creation (Phase 5), skip the review loop and merge
- **`--review-with <agent[,agent,...]>`**: which reviewer(s) run the Phase 6 review loop on each PR. Accepted slugs: `copilot`, `codex`, `agy` (aliases `gemini` / `antigravity` — all run the Antigravity CLI's `agy` binary), `claude`, `grok`, `ollama` (bare `ollama` auto-selects the most capable installed coding model; `ollama[<model>]` pins a specific installed model, e.g. `ollama[qwen2.5-coder:32b]` — strip the bracket into a per-entry `OLLAMA_MODEL`; `codex`/`claude`/`agy`/`grok` likewise accept a `<agent>[<model>]` bracket — e.g. `codex[o3]`, `claude[claude-opus-4-8]`, `grok[grok-code-fast-1]` — stripped into a per-entry `REVIEW_MODEL`, empty → the reviewer's built-in default; `copilot` and `@<login>` take no model bracket), or an arbitrary GitHub login `@<login>` — any GitHub user or App/bot (e.g. `@octocat`, `@org-review-bot`, `@some-app[bot]`); slashdo requests its review on the PR and waits for it (GitHub only, never posts an approval itself) (comma-separated, ordered list; split on `,`, trim whitespace, normalize `gemini`/`antigravity` → `agy`, dedupe preserving first-occurrence order, with each model-taking agent's (`codex`/`claude`/`agy`/`grok`/`ollama`) `[<model>]` bracket suffix part of the dedup identity). Record as `REVIEW_AGENTS`. **There is no built-in default** — if omitted, leave `REVIEW_AGENTS` **unset for now**; the saved-defaults step below fills it from `/do:config` if a default exists, and **only if it is still unset after that** is `REVIEW_AGENTS=[]` (Phase 6 skipped, PRs left open without merging — see Phase 6). `copilot` is never added implicitly. Any slot may end in `~opt` (e.g. `ollama~opt`, `ollama[qwen2.5-coder:32b]~opt`) to mark that reviewer **optional/non-blocking** — still requested and its findings still fixed, but an inconclusive result from it (timeout/skipped/incomplete/no-verdict) never blocks the PR merge (a hard-error from it still does); strip `~opt` into a per-entry `{OPTIONAL}` flag before slug parsing, and it is **not** part of the dedup identity (`ollama~opt` == `ollama`, optional-wins on collapse). A slot may also end in `~max=<n>` (e.g. `claude~max=2`, `ollama~max=1`) to cap how many review → fix → re-review cycles **that one reviewer** runs — the per-entry form of `--review-iterations`, and the only way to move the local-agent / `ollama` caps (otherwise fixed at 3), so one run can budget each reviewer separately (`claude~max=2,ollama~max=1,codex~max=3`). `<n>` is a non-negative integer (`0` = loop until clean, bounded by each loop's 10-iteration guardrail); strip it into a per-entry `{ENTRY_MAX}` alongside `~opt` — both suffixes come off the right of the token in either order before slug parsing, and neither is part of the dedup identity (the cap comes from the first occurrence that carried a `~max`, so a bare earlier occurrence does not erase a later cap). A reviewer that stops because it reached a `~max` you set returns `capped`, which is clean-equivalent for the merge gate. See `lib/multi-reviewer-loop.md`. Abort on an unknown slug with `Unknown --review-with value: {value}. Use one of: copilot, codex, agy, claude, grok, ollama, @<login> (each optionally suffixed ~opt and/or ~max=<n>).` The reserved token `none` (case-insensitive) is **not** validated as a slug — `--review-with none` means no reviewer (set `REVIEW_AGENTS=[]`) and overrides any saved `review-with` default.
- **`--review-stop-on-findings`** / **`--review-stop-on-clean`** (mutually exclusive): forwarded to the multi-reviewer loop for each PR; control when a per-PR reviewer list stops early. Set `REVIEW_STOP_MODE` (`all` default, `on-findings`, or `on-clean`). If both are present, abort with `--review-stop-on-findings and --review-stop-on-clean cannot be combined`.
Expand All @@ -25,7 +25,7 @@ After parsing the review flags above, apply any **saved defaults** (set via `/do

!`cat ~/.claude/lib/review-config-defaults.md`

- **`--issues`** / **`--no-issues`** / **`--issues-label <name>`**: track deferred findings as GitHub/GitLab issues instead of PLAN.md lines (see Phase 2). `--issues` sets `ISSUE_MODE=true`; `--no-issues` forces `ISSUE_MODE=false`. If the user passes **neither**, take `ISSUE_MODE` from the saved `issues` default resolved above (built-in default `false`). Set `PLAN_LABEL` from `--issues-label`, else the saved `issues-label` default, else `plan`.
- **`--issues`** / **`--no-issues`** / **`--issues-label <name>`**: selects **where deferred findings are recorded** — GitHub/GitLab issues instead of PLAN.md lines (see Phase 2). **It does NOT change what the run does**: remediation, PRs, CI, the review loop, and merge all proceed exactly as normal. To audit and file work *without* remediating, combine it with **`--scan-only`**. `--issues` sets `ISSUE_MODE=true`; `--no-issues` forces `ISSUE_MODE=false`. If the user passes **neither**, take `ISSUE_MODE` from the saved `issues` default resolved above (built-in default `false`). Set `PLAN_LABEL` from `--issues-label`, else the saved `issues-label` default, else `plan`.
- **Path filter**: limit scanning scope to specific directories or files
- **Focus areas**: e.g., "security only", "platform coverage and accessibility"

Expand Down Expand Up @@ -621,7 +621,9 @@ For each file touched by multiple categories, document why it was assigned to on
| TOTAL | ... | ... | ... | ... | ... |
```

**GATE: If `--scan-only` was passed, STOP HERE.** Print the summary and exit.
**GATE: If `--scan-only` was passed, STOP HERE** — but not before doing the one thing a scan-only run in issue mode exists to do: **when `ISSUE_MODE` is also true, file every surviving finding as an issue first**, then print the summary and exit. (When `ISSUE_MODE` is false, just print the summary and exit.)

**Filing every surviving finding** means all of them — not just the ones the disposition rules would defer. A scan-only run remediates nothing, so "deferred" covers the whole set; the filed issues ARE the run's output. Apply the same labels, dedup-against-`EXISTING_ISSUES`, and title/body rules the disposition partial specifies, and report the created and reused `#<number>`s in the summary. Do not open a worktree or write any code.

## Phase 3: Worktree Remediation

Expand Down
8 changes: 5 additions & 3 deletions commands/do/better.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Run the full DevSecOps lifecycle: audit the codebase with up to 10 deduplicated

Parse `$ARGUMENTS` for:
- **`--interactive`**: pause at each decision point for user approval
- **`--scan-only`**: run Phase 0 + 1 + 2 only (audit and plan), skip remediation
- **`--scan-only`**: run Phase 0 + 1 + 2 only (audit and plan), skip remediation — no worktree, no code changes, no PRs. **When `ISSUE_MODE` is also true, this is the "audit and file the work, don't touch my code" combination**: every surviving finding is filed as a labelled tracker issue before the run exits, not just the deferred subset (see the Phase 2 gate). `--scan-only` is the flag that stops the pipeline; `--issues` only chooses where findings are recorded
- **`--simplify-only`** (alias: **`--refactor-only`**): narrow the run to structural quality — refactoring, architecture, DRY, simplification, and cognitive load. Set `SIMPLIFY_ONLY=true`. The pipeline is unchanged (worktree remediation → per-category PRs → CI → review loop → merge); only the audit roster, the category set, and the remediation contract narrow. See [Simplify-Only Mode](#simplify-only-mode---simplify-only) for the exact deltas. `/do:simplify` is the shorthand for `/do:better --simplify-only`
- **`--no-merge`**: run through PR creation (Phase 5), skip the review loop and merge
- **`--review-with <agent[,agent,...]>`**: which reviewer(s) run the Phase 6 review loop on each PR. Accepted slugs: `copilot`, `codex`, `agy` (aliases `gemini` / `antigravity` — all run the Antigravity CLI's `agy` binary), `claude`, `grok`, `ollama` (bare `ollama` auto-selects the most capable installed coding model; `ollama[<model>]` pins a specific installed model, e.g. `ollama[qwen2.5-coder:32b]` — strip the bracket into a per-entry `OLLAMA_MODEL`; `codex`/`claude`/`agy`/`grok` likewise accept a `<agent>[<model>]` bracket — e.g. `codex[o3]`, `claude[claude-opus-4-8]`, `grok[grok-code-fast-1]` — stripped into a per-entry `REVIEW_MODEL`, empty → the reviewer's built-in default; `copilot` and `@<login>` take no model bracket), or an arbitrary GitHub login `@<login>` — any GitHub user or App/bot (e.g. `@octocat`, `@org-review-bot`, `@some-app[bot]`); slashdo requests its review on the PR and waits for it (GitHub only, never posts an approval itself) (comma-separated, ordered list; split on `,`, trim whitespace, normalize `gemini`/`antigravity` → `agy`, dedupe preserving first-occurrence order, with each model-taking agent's (`codex`/`claude`/`agy`/`grok`/`ollama`) `[<model>]` bracket suffix part of the dedup identity). Record as `REVIEW_AGENTS`. **There is no built-in default** — if omitted, leave `REVIEW_AGENTS` **unset for now**; the saved-defaults step below fills it from `/do:config` if a default exists, and **only if it is still unset after that** is `REVIEW_AGENTS=[]` (Phase 6 skipped, PRs left open without merging — see Phase 6). `copilot` is never added implicitly. Any slot may end in `~opt` (e.g. `ollama~opt`, `ollama[qwen2.5-coder:32b]~opt`) to mark that reviewer **optional/non-blocking** — still requested and its findings still fixed, but an inconclusive result from it (timeout/skipped/incomplete/no-verdict) never blocks the PR merge (a hard-error from it still does); strip `~opt` into a per-entry `{OPTIONAL}` flag before slug parsing, and it is **not** part of the dedup identity (`ollama~opt` == `ollama`, optional-wins on collapse). A slot may also end in `~max=<n>` (e.g. `claude~max=2`, `ollama~max=1`) to cap how many review → fix → re-review cycles **that one reviewer** runs — the per-entry form of `--review-iterations`, and the only way to move the local-agent / `ollama` caps (otherwise fixed at 3), so one run can budget each reviewer separately (`claude~max=2,ollama~max=1,codex~max=3`). `<n>` is a non-negative integer (`0` = loop until clean, bounded by each loop's 10-iteration guardrail); strip it into a per-entry `{ENTRY_MAX}` alongside `~opt` — both suffixes come off the right of the token in either order before slug parsing, and neither is part of the dedup identity (the cap comes from the first occurrence that carried a `~max`, so a bare earlier occurrence does not erase a later cap). A reviewer that stops because it reached a `~max` you set returns `capped`, which is clean-equivalent for the merge gate. See `lib/multi-reviewer-loop.md`. Abort on an unknown slug with `Unknown --review-with value: {value}. Use one of: copilot, codex, agy, claude, grok, ollama, @<login> (each optionally suffixed ~opt and/or ~max=<n>).` The reserved token `none` (case-insensitive) is **not** validated as a slug — `--review-with none` means no reviewer (set `REVIEW_AGENTS=[]`) and overrides any saved `review-with` default.
Expand All @@ -27,7 +27,7 @@ After parsing the review flags above, apply any **saved defaults** (set via `/do
!`cat ~/.claude/lib/review-config-defaults.md`

- **`--strict`** (alias: **`--nuclear`**): enable the Structural Ambition agent (10th audit agent) and promote its blocker-tier findings to CRITICAL severity for remediation. Flags file-size growth past 1000 lines, ad-hoc conditionals bolted onto unrelated flows, thin wrappers, boundary leaks, and missed code-judo simplifications. Set `STRICT_MODE=true` when present. `--simplify-only` implies it — set `STRICT_MODE=true` whenever `SIMPLIFY_ONLY=true`, whether or not `--strict` was passed
- **`--issues`** / **`--no-issues`** / **`--issues-label <name>`**: track deferred findings as GitHub/GitLab issues instead of PLAN.md lines (see Phase 2). `--issues` sets `ISSUE_MODE=true`; `--no-issues` forces `ISSUE_MODE=false`. If the user passes **neither**, take `ISSUE_MODE` from the saved `issues` default resolved above (built-in default `false`). Set `PLAN_LABEL` from `--issues-label`, else the saved `issues-label` default, else `plan`.
- **`--issues`** / **`--no-issues`** / **`--issues-label <name>`**: selects **where deferred findings are recorded** — GitHub/GitLab issues instead of PLAN.md lines (see Phase 2). **It does NOT change what the run does**: remediation, per-category PRs, CI, the review loop, and merge all proceed exactly as normal. To audit and file work *without* remediating, combine it with **`--scan-only`**. `--issues` sets `ISSUE_MODE=true`; `--no-issues` forces `ISSUE_MODE=false`. If the user passes **neither**, take `ISSUE_MODE` from the saved `issues` default resolved above (built-in default `false`). Set `PLAN_LABEL` from `--issues-label`, else the saved `issues-label` default, else `plan`.
- **Path filter**: limit scanning scope to specific directories or files
- **Focus areas**: e.g., "security only", "DRY and bugs"

Expand Down Expand Up @@ -491,7 +491,9 @@ When `SIMPLIFY_ONLY=true`, emit only the [`SIMPLIFY_CATEGORIES`](#the-category-s

Omit the **UX** row when `HAS_UI=false`, the **Structural** row when `STRICT_MODE=false`, and the **Cognitive Load** row when `SIMPLIFY_ONLY=false`. When `SIMPLIFY_ONLY=true`, keep only the [`SIMPLIFY_CATEGORIES`](#the-category-set) rows.

**GATE: If `--scan-only` was passed, STOP HERE.** Print the summary and exit.
**GATE: If `--scan-only` was passed, STOP HERE** — but not before doing the one thing a scan-only run in issue mode exists to do: **when `ISSUE_MODE` is also true, file every surviving finding as an issue first**, then print the summary and exit. (When `ISSUE_MODE` is false, just print the summary and exit.)

**Filing every surviving finding** means all of them — not just the ones the disposition rules would defer. A scan-only run remediates nothing, so "deferred" covers the whole set; the filed issues ARE the run's output. Apply the same labels, dedup-against-`EXISTING_ISSUES`, and title/body rules the disposition partial specifies, and report the created and reused `#<number>`s in the summary. Do not open a worktree or write any code.

## Phase 3: Worktree Remediation

Expand Down
Loading