Make mutation failures actionable #648

Merged
barrettruth merged 1 commit from fix/636-actionable-mutation-failures into main 2026-05-06 21:21:40 +00:00
Owner

Closes #636

Summary

  • Make the shared command formatter render one human detail only: context: detail.
  • Stop rendering secondary stream labels or raw backend commands in normal user-facing errors.
  • Give mutation operations specific failure context for PR, issue, release, and CI actions.
  • Forward the same human-readable failure message to on_failure callbacks so picker recovery paths receive actionable text.
  • Return only backend failure detail from Forgejo draft title patching, then let the shared operation layer add the PR action context.

Messaging

Before After
merge failed: blocked by branch protection, callback receiving nil failed to merge PR #42: blocked by branch protection, callback receiving the same string
delete failed: no command output failed to delete release v1.2.3: no command output
merge failed: cannot merge cleanly; stdout: pull request remains open merge failed: cannot merge cleanly
merge failed: blocked (command: tea pr merge 42 --repo owner/repo) merge failed: blocked

Verification

  • Before repro: system nvim v0.12.2, isolated XDG dirs, vim.pack, and lz.n against a2ae078 reproduced the weak merge failure: log had generic mutation context and on_failure received nil.
  • After repro: same system nvim/vim.pack/lz.n flow against eb4fabe produced failed to merge PR #42: blocked by branch protection in both the log and callback.
  • just test spec/system_spec.lua spec/ops_spec.lua spec/sources_spec.lua
  • just test
  • just lint
  • nix develop .#ci --command just ci
Closes #636 ## Summary - Make the shared command formatter render one human detail only: `context: detail`. - Stop rendering secondary stream labels or raw backend commands in normal user-facing errors. - Give mutation operations specific failure context for PR, issue, release, and CI actions. - Forward the same human-readable failure message to `on_failure` callbacks so picker recovery paths receive actionable text. - Return only backend failure detail from Forgejo draft title patching, then let the shared operation layer add the PR action context. ## Messaging | Before | After | | --- | --- | | `merge failed: blocked by branch protection`, callback receiving `nil` | `failed to merge PR #42: blocked by branch protection`, callback receiving the same string | | `delete failed: no command output` | `failed to delete release v1.2.3: no command output` | | `merge failed: cannot merge cleanly; stdout: pull request remains open` | `merge failed: cannot merge cleanly` | | `merge failed: blocked (command: tea pr merge 42 --repo owner/repo)` | `merge failed: blocked` | ## Verification - Before repro: system `nvim` v0.12.2, isolated XDG dirs, `vim.pack`, and `lz.n` against `a2ae078` reproduced the weak merge failure: log had generic mutation context and `on_failure` received `nil`. - After repro: same system `nvim`/`vim.pack`/`lz.n` flow against `eb4fabe` produced `failed to merge PR #42: blocked by branch protection` in both the log and callback. - `just test spec/system_spec.lua spec/ops_spec.lua spec/sources_spec.lua` - `just test` - `just lint` - `nix develop .#ci --command just ci`
Make mutation failures actionable
All checks were successful
quality / Test (pull_request) Successful in 12s
quality / Format (pull_request) Successful in 15s
quality / Lint (pull_request) Successful in 16s
54bf3ca707
barrettruth force-pushed fix/636-actionable-mutation-failures from 54bf3ca707
All checks were successful
quality / Test (pull_request) Successful in 12s
quality / Format (pull_request) Successful in 15s
quality / Lint (pull_request) Successful in 16s
to eb4fabea0b
All checks were successful
quality / Test (pull_request) Successful in 10s
quality / Format (pull_request) Successful in 13s
quality / Lint (pull_request) Successful in 14s
2026-05-06 21:20:20 +00:00
Compare
barrettruth deleted branch fix/636-actionable-mutation-failures 2026-05-06 21:21:40 +00:00
Sign in to join this conversation.
No description provided.