Skip to content

feat(0017): undo group transactions — begin/end/rollback, envelope rollback_available, HL 28 - #38

Closed
Ryan-AI-Studios wants to merge 36 commits into
maorcc:mainfrom
Ryan-AI-Studios:feature/0017-undo-group-transactions
Closed

feat(0017): undo group transactions — begin/end/rollback, envelope rollback_available, HL 28#38
Ryan-AI-Studios wants to merge 36 commits into
maorcc:mainfrom
Ryan-AI-Studios:feature/0017-undo-group-transactions

Conversation

@Ryan-AI-Studios

@Ryan-AI-Studios Ryan-AI-Studios commented Aug 4, 2026

Copy link
Copy Markdown

Summary

Track 0017-UndoGroupTransactions: agent multi-step undo transactions via GIMP undo_group_*, honest error-envelope rollback_available / transaction_id, wall-clock timeout force-close, HL 28 tools, and ship gimp_mcp_tx.py as the 10th plug-in file.

Changes

  • gimp_mcp_tx.py: pure mint/validate/TxStack/reap/recent helpers (EXPECTED Add CodeRabbit configuration for automated code reviews #10 + packaging triad)
  • Plugin: begin/end/rollback/status/force_close; wall-clock 300s reap; depth 8; close_image force-end before delete; send-path enrich for mid-TX errors
  • Envelope: remove force-false; plugin SoT on TCP; host open-TX hint for pre-TCP only
  • MCP: HL undo_group_begin / end / rollback (28 total); advanced status/force_close
  • Codes: TX_* → CLI exit 6; cap undo_group_transactions: true

Review

  • Internal R1 FAIL → fix → R2 PASS
  • Codex R1 FAIL → fix → Codex R2 final PASS WITH DEFERRED P3

Residual (deferred)

  • Live GIMP operator matrix (APPDATA 10-file install / 0018)
  • _last_cmd_params thread-local for multi-client concurrent enrich

Test plan

  • uv run ruff check .
  • uv run basedpyright
  • uv run pytest -m "not integration and not slow"
  • CI green

Summary by CodeRabbit

  • New Features

    • Added the gimp-agent command-line interface for diagnostics, authenticated plugin checks, recipes, verification, comparison, and batch processing.
    • Added secure authentication, workspace restrictions, audit logging, structured errors, stable handles, checkpoints, undo transactions, and non-destructive filters.
    • Added verified exports with alpha preservation, collision handling, visible-composite snapshots, coordinate mappings, and image comparison.
    • Added high-level and advanced tool modes with recipe support.
  • Documentation

    • Expanded setup, security, protocol, architecture, workflow, and export guidance.
  • Tests

    • Added extensive offline coverage for security, CLI behavior, exports, snapshots, recipes, transactions, filters, and state validation.

Ryan and others added 30 commits August 2, 2026 08:17
Add uv dev toolchain (ruff, basedpyright, pytest), project CI with
Node-24-ready Actions, gitignore for local agent/conductor governance,
offline smoke tests, and docs/planner-handoff.md for cold-start planners.
Includes small gimp_mcp_server typing/format fixes for the new gate.
Document 0001 bootstrap complete, 0002 quality stabilization as next,
and the full path through 0028 final product polish.
Full product ruff/format green; scripts layout; setup-uv@v9.0.0; lint.yml retired; planner-handoff policy.

Ledger: 83598dee-78b5-4c0a-8975-96a7b5cd15c4
…th jail

Track 0003: Class A/B exec gates, AF_INET 127.0.0.1, session auth, path jail, audit. CI green. Codex final PASS WITH DEFERRED P3.
…mapping

Visible composite snapshots (dup+merge), image_index, ToolResult structuredContent mapping, temp policy, fail-closed selection/PNG validation. Codex final PASS WITH DEFERRED P3.
* feat(export): add gimp_mcp_export host module + offline alpha tests

* fix(export): alpha-preserving merge-on-dup + file-*-export + verify tool

* docs: Issue 16 alpha export defaults, install gimp_mcp_export.py

* fix(export): recursive alpha preflight + structured MCP errors

IR1-01: walk layer groups recursively in preflight/verify_alpha
IR1-02: return structured export error dicts from MCP export_image
IR1-04: fail-closed when preserve_alpha and drawable unset
IR1-05: greps, type-4 PNG fixture, structured-error source tests

* fix(export): codex P1/P2 — no silent format fallback, fail-closed RGBA8, batch metadata

* fix(export): format README; drop accidental conductor review from tree

Keep conductor/ gitignored local-only. Ruff-format README code fences for CI.

* docs(0005): mark AlphaExportCorrectness complete in planner handoff

Issue 16 closed: merge-on-dup export, IHDR ALPHA_LOST, verify_alpha_channel.
Next product track: 0006 StateManifestOrientation (placeholder plan).

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
Schema-versioned orient_workspace state-manifest v1; host finalize; recursive layers; provisional handles; image_index metadata hygiene. Codex engineering PASS WITH DEFERRED P3 (live matrix).
Ledger: f13ebc80-dc77-4722-831e-68b1858c6a0f
…select_* (#6)

Stable handle registry: gimp_mcp_handles, process-unique session_epoch, generation tombstones, structural bumps, select_image/select_layers. Codex PASS WITH DEFERRED P3.
Next product track is 0008-CoordinateModelAndExif (placeholder).
PR #6 / main@33df2b5 delivered generation registry, STALE_HANDLE, select_*.

Ledger: 211b63de-c672-4bfe-9143-007559ba8877

Co-authored-by: Ryan <rbourgoin@gmail.com>
…#8)

* feat(0008): CoordinateModelAndExif — coords, mapping, normalize, map_*

Ship gimp_mcp_coords as 7th plug-in file (preview/layer math, ordered
ORIENTATION_OPS, declaration validate, half-even rounding). Enrich mapping
metadata on three paths (build_mapping_metadata + plugin bitmap flatten +
server ToolResult pass-through). Add normalize_image_orientation (default
assume_pixels_upright; trust_tag opt-in; direct rotate/flip; both EXIF tags;
METADATA_WRITE_FAILED; self gen-bump). Session _orientation_normalized synced
with gen prune. Host map_* x4. Capability coordinate_exif_normalized true.

Ledger: a184eb50-f0d4-42c6-b069-1061eef57ad3

* fix(0008): undo pixel ops when normalize set_metadata fails

Call image.undo() after the undo group ends if metadata write fails and
trust_tag pixel ops ran, so the canvas is not left rotated with a stale tag.

Ledger: a184eb50-f0d4-42c6-b069-1061eef57ad3

* fix(0008): undo on mid-op normalize exceptions (ops_started)

Ensure trust_tag pixel ops that raise after partial transform call
image.undo() after undo_group_end, not only the metadata-false path.

Ledger: a184eb50-f0d4-42c6-b069-1061eef57ad3

* fix(0008): fail-closed gboolean ops, invalid EXIF honesty, plan tests

- Check image.flip/rotate and undo_group_* for explicit False
- Keep present-but-invalid orientation for honesty; clamp for manifest
- plan_normalize_ops offline behavioral tests; README install count

Ledger: a184eb50-f0d4-42c6-b069-1061eef57ad3

* fix(0008): fail-closed undo_group_end (no success on False)

Do not swallow undo_group_end gboolean False; re-raise body errors after
end so generation is never bumped on group-close failure.

Ledger: a184eb50-f0d4-42c6-b069-1061eef57ad3

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
PR #8 / main@8970ad2; Codex PASS WITH DEFERRED P3; next=0009.

Co-authored-by: Ryan <rbourgoin@gmail.com>
…kpoints, confirm_destructive (#10)

* feat(0009): gimp_mcp_policy + codes + tests + install

Ship 8th plug-in file for labels/paths/sidecar/integrity hash;
POLICY_DENIED/CONFIRM_REQUIRED/CHECKPOINT_* codes; offline tests;
pyproject + README install lists.

Ledger: 3a04bc4b-8616-4512-9529-40c0f0c9f4d4

* feat(0009): Source_Immutable, confirm_destructive, checkpoints

- ensure_source_immutable with parasite group + central mutable resolve
- confirm_destructive on live flatten/merge/rotate free-angle/resize fill
- checkpoint_create/restore with jailed paths + integrity sidecar
- orient tattoo/protected; capabilities source_immutable_policy + checkpoints
- MCP tools + protocol/README agent intake order

Ledger: 3a04bc4b-8616-4512-9529-40c0f0c9f4d4

* fix(0009): tighten confirm-scope wiring tests and orient-snapshot honesty

Pin free-angle / will_flatten branch structure for confirm_destructive.
Document include_orient_snapshot=true as note-only (no embedded dump).

Ledger: 3a04bc4b-8616-4512-9529-40c0f0c9f4d4

* fix(0009): address Codex P1/P2 — bool coerce, idempotent ensure, XCF partial

- Use export.coerce_bool for confirm_destructive / allow_source_mutation / overwrite
- Skip working copies on re-ensure (session set + name suffix); no gen bump on no-op
- Save checkpoint XCF via .partial then os.replace; check PDB status + non-empty
- Document allow_source_mutation as raw-TCP recovery only (not MCP mutators)

Ledger: 3a04bc4b-8616-4512-9529-40c0f0c9f4d4

* fix(0009): strict coerce_bool + safer working-name skip + restore bools

- coerce_bool fail-closed for non-scalar JSON (list/dict → default)
- Name-based working skip only when policy group already has children
- checkpoint_restore close_prior/verify_hash use coerce_bool

Ledger: 3a04bc4b-8616-4512-9529-40c0f0c9f4d4

* fix(0009): durable Source_Immutable deny via group ancestry + hydrate

_assert_mutable also denies descendants of parasite-marked group.
Hydrate protected set on ensure, open_image, orient, checkpoint_restore.
Strict coerce_bool non-scalar fail-closed already in export.

Ledger: 3a04bc4b-8616-4512-9529-40c0f0c9f4d4

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
#11)

Record PR #10 / main@25e93ba completion notes; next track 0010.

Co-authored-by: Ryan <rbourgoin@gmail.com>
…stMCP (#12)

* 0010: high-level MCP surface (~18 tools) on real FastMCP

Migrate from mcp.server.fastmcp shim to real fastmcp.FastMCP with include_tags + ToolAnnotations. Default surface is 18 HL tools; GIMP_MCP_ADVANCED_TOOLS=1 exposes full advanced surface.

Ledger: 5272272a-d519-4e72-9635-d27e3267c1fb

* fix(0010): handle-first save/export/verify/close + by_color layer_id

Wire plugin mutators through _resolve_image_from_params so HL handle
params cannot silently target image 0. Fail closed on explicit layer_id
for select_by_color. Strengthen offline handle tests; PROTOCOL design names.

Ledger: 5272272a-d519-4e72-9635-d27e3267c1fb

* fix(0010): fail-closed prior handle on restore; honest composite index

checkpoint_restore close_prior with invalid handle returns STALE/FOREIGN
instead of silent skip. Derive open-list image_index after handle resolve
for composite mapping. Align create_selection layer_handle docs; tests.

Ledger: 5272272a-d519-4e72-9635-d27e3267c1fb

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
Ledger: 5272272a-d519-4e72-9635-d27e3267c1fb

Co-authored-by: Ryan <rbourgoin@gmail.com>
…st_id audit (#14)

* feat(0011): structured error envelope v1 + request_id audit correlation

Implement product error envelope, single-line ToolError wire, CODE matrix (PARTIAL_MUTATION, CONNECTION_FAILED), host/plugin split audit files, and request_id correlation (contextvars host, threading.local plugin).

- export_image raises ToolError on ALPHA_LOST (H1; details preserved)

- _jail_path_or_raise re-raises SecurityError (H5)

- send_command params copy + _request_id; CONNECTION_FAILED on transport

- @with_structured_error on all MCP tools; structured_errors capability

- docs: PROTOCOL recovery table, SECURITY audit/traceback policy, README

Ledger: 6dc55b22-8287-44cf-a6d3-1fbbfb37327a

* fix(0011): call_api ToolError path + affected_handles on INTERNAL (M5)

Ledger: 6dc55b22-8287-44cf-a6d3-1fbbfb37327a

* fix(0011): parse_tool_error_text handles message containing ' | '

Codex P1: rfind alone selected the pipe inside JSON error.message when the
human message also contained the delimiter. Try every ' | ' candidate from
the right until a valid envelope parses. Regression test added.

Ledger: 6dc55b22-8287-44cf-a6d3-1fbbfb37327a

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
…#15)

Ledger: 6dc55b22-8287-44cf-a6d3-1fbbfb37327a

Co-authored-by: Ryan <rbourgoin@gmail.com>
…t codes (#16)

* feat(cli): 0012 gimp-agent doctor probe exit codes

Ship host package gimp_agent/ with entrypoint gimp-agent:
- argparse CLI: doctor [--strict], probe [--timeout], version, codes
- CODE_* / CLI-local → exit 0-12 map + reverse table
- path discovery (env/PATH/App Paths/install dirs + GIMP 3.* semver)
- doctor ordered checks; probe auth JSON get_gimp_info
- JSON envelope (--json / GIMP_AGENT_JSON); offline tests
- docs: README CLI section; protocol full exit table

* fix(cli): 0012 address review lows (docs, tests, timeout)

Document non-strict doctor (exit 0 + ok:false) and probe TIMEOUT→9.
Add offline tests for non-strict doctor and TimeoutError path.
Remove dead stderr branch in jsonio.emit (human mode stays stdout).

* fix(cli): 0012 codex P1/P2 — json flag, probe success, version rc

* fix(cli): 0012 env JSON mode + strict JSON for invalid timeout

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
…export (#18)

* feat(0013): atomic XCF save and export with collision policy

Add gimp_mcp_atomic pure helpers, OUTPUT_COLLISION/VERIFY_FAILED codes,
temp+os.replace writers for save_xcf/export_image, CLI save-xcf/export,
atomic capabilities true, and 8-file plugin ship set.

* docs(0013): fix honesty — atomic save/export and ALPHA_LOST final_intact

Remove README non-atomic table claim; align protocol ALPHA_LOST and capabilities with verify-on-temp; fold planner-handoff 0013 notes.

Ledger: df79fd18-00cb-4850-84ce-f9d9804d3b90

* fix(0013): flatten export success results (no nested status)

Public export_image strips helper status so results match DoD-4 flat manifest. Tests and mocks updated.

Ledger: df79fd18-00cb-4850-84ce-f9d9804d3b90

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
PR #18 / main@5763a69; Codex PASS WITH DEFERRED P3; next=0014.

Co-authored-by: Ryan <rbourgoin@gmail.com>
…nly CLI (#20)

Host gimp_mcp_verify: PNG defilter 0-4 (Paeth), MAE/max_ae/changed, global SSIM,
refine_should_stop, grayscale diff, optional ImageMagick; budgets 50M/500MiB.
MCP HL compare_images + verify_artifact (catalog 20); pixel_verification true;
alpha_snapshot stays false. CLI gimp-agent compare/verify host-only (no TCP);
--spec workspace-jailed; VERIFY_FAILED exit 8. Doctor magick/compare info.
Ledger: a5957e9d-3a46-46f2-93fe-4a857a3bcca2

Co-authored-by: Ryan <rbourgoin@gmail.com>
#21)

Product main@00cc49a (PR #20). HL 20, host-only CLI compare/verify, pixel_verification.
Next focus: 0015-RecipeLibrary (placeholder).

Co-authored-by: Ryan <rbourgoin@gmail.com>
)

* feat(0015): recipe registry load/validate + package-data JSON

Add gimp_mcp_recipes.py (stdlib JSON registry, whole-value $name
interpolation, semver latest, fail-closed load) and five recipes under
gimp_agent/recipes/ as setuptools package-data.

Ledger: 59d02950-cb04-4591-bac6-e820d18c0e6a

* feat(0015): MCP list_recipes apply_recipe HL 22

Expose list_recipes + apply_recipe as HL tools; catalog 20→22; capability
recipe_library=true (batch_interpreter stays false).

Ledger: 59d02950-cb04-4591-bac6-e820d18c0e6a

* feat(0015): CLI recipes run batch

Add gimp-agent recipes/run/batch with --inputs append, --input-glob,
continue-on-fail batch semantics, and exit 12 for unknown recipe ids.

Ledger: 59d02950-cb04-4591-bac6-e820d18c0e6a

* test(0015): offline recipe matrix

Cover load fail-closed, interpolation, compare-artifacts host, web-export
scale with advanced unset, created_paths rollback, batch continue-on-fail,
exiftool shell=False, HL 22, and package resources.

Ledger: 59d02950-cb04-4591-bac6-e820d18c0e6a

* docs(0015): README protocol recipes

Document HL 22, recipe library, CLI recipes/run/batch, and mark 0015
in progress in planner-handoff.

Ledger: 59d02950-cb04-4591-bac6-e820d18c0e6a

* fix(0015): rebind output_path after version collision; batch exit 10

Ledger: 59d02950-cb04-4591-bac6-e820d18c0e6a

* fix(0015): batch collision/params/XOR; load-time defaults; glob safety

Ledger: 59d02950-cb04-4591-bac6-e820d18c0e6a

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
PR #22 / main@51adaeb; Codex PASS WITH DEFERRED P3; next focus 0016.

Co-authored-by: Ryan <rbourgoin@gmail.com>
…ers[], HL 25 (#24)

* feat(0016): NDE DrawableFilter tools — apply/edit/remove, orient filters[], HL 25

* fix(0016): address internal review mediums (error codes, edit order, probe mock, SECURITY)

* fix(0016): Codex R1 — HL layer_handle required; UNSUPPORTED on filter new failures

* docs(0016): mark NdeFilterTools complete in planner handoff

Record HL 25, handle-first NDE tools, offline waiver, and next track 0017.

---------

Co-authored-by: Ryan <rbourgoin@gmail.com>
Ryan added 6 commits August 3, 2026 23:02
…l rollback pop

- Plugin send-path enriches error dicts with rollback_available + transaction_id
  when an open agent TX exists (DoD-3 / §2.13 honesty)
- Dispatch reap resolves layer_handle and other handle-like params
- Host contextvar image_id wires open-TX hint for mutator ToolErrors
- Partial rollback pops stack after undo_group_end success if undo fails
- Prune agent TX stacks in _sync_image_generations for closed images
…path

Codex R1: image.undo() gboolean False was treated as success; host open-TX
hint could stale-advertise rollback after plugin reap. Plugin SoT on TCP
errors; clear host hint on close_image; docs 25→28 HL.
@Ryan-AI-Studios

Copy link
Copy Markdown
Author

Opened against upstream by mistake; product tracks merge to Ryan-AI-Studios/gimp-mcp fork.

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: bf8c24f4-95f7-4edd-8694-c759aa5b92c6

📥 Commits

Reviewing files that changed from the base of the PR and between 09bfb2d and 2e3ddfb.

⛔ Files ignored due to path filters (3)
  • scripts/continuous_edit_test/files/bg_night_2048.png is excluded by !**/*.png
  • scripts/continuous_edit_test/files/winry_joy.png is excluded by !**/*.png
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (64)
  • .github/workflows/ci.yml
  • .github/workflows/lint.yml
  • .gitignore
  • .pre-commit-config.yaml
  • CLAUDE.md
  • GIMP_MCP_PROTOCOL.md
  • README.md
  • SECURITY.md
  • agent_edit_demo.py
  • bg_remove.py
  • bg_remove_iterative.py
  • docs/best_practices.md
  • docs/iterative_workflow.md
  • docs/planner-handoff.md
  • gimp-mcp-plugin.py
  • gimp_agent/__init__.py
  • gimp_agent/__main__.py
  • gimp_agent/cli.py
  • gimp_agent/doctor.py
  • gimp_agent/exit_codes.py
  • gimp_agent/jsonio.py
  • gimp_agent/paths.py
  • gimp_agent/probe.py
  • gimp_agent/recipes/compare-artifacts.json
  • gimp_agent/recipes/exif-normalize.json
  • gimp_agent/recipes/exif-strip.json
  • gimp_agent/recipes/transparent-png.json
  • gimp_agent/recipes/web-export.json
  • gimp_mcp_atomic.py
  • gimp_mcp_coords.py
  • gimp_mcp_export.py
  • gimp_mcp_filters.py
  • gimp_mcp_handles.py
  • gimp_mcp_policy.py
  • gimp_mcp_recipes.py
  • gimp_mcp_security.py
  • gimp_mcp_server.py
  • gimp_mcp_snapshot.py
  • gimp_mcp_state.py
  • gimp_mcp_surface.py
  • gimp_mcp_tx.py
  • gimp_mcp_verify.py
  • pyproject.toml
  • run_tests.py
  • schemas/state-manifest.v1.json
  • scripts/add_text_metadata.py
  • scripts/continuous_edit_test/continuous_edit_test.py
  • tests/test_atomic_io.py
  • tests/test_coords.py
  • tests/test_export_alpha.py
  • tests/test_filters.py
  • tests/test_gimp_agent_cli.py
  • tests/test_handles.py
  • tests/test_high_level_surface.py
  • tests/test_layer_policy.py
  • tests/test_quality_smoke.py
  • tests/test_recipes.py
  • tests/test_security_policy.py
  • tests/test_snapshot_composite.py
  • tests/test_snapshot_mapping.py
  • tests/test_state_manifest.py
  • tests/test_structured_errors.py
  • tests/test_tx.py
  • tests/test_verify.py

Walkthrough

The PR adds authenticated GIMP MCP transport, structured security and editing policies, visible-composite snapshots, stable handles, checkpoints, filters, transactions, PNG verification, a host CLI, recipes, packaging, CI, documentation, and extensive offline tests.

Changes

GIMP MCP platform

Layer / File(s) Summary
Security, state, export, and workflow helpers
gimp_mcp_*.py
Adds reusable policies for authentication, path confinement, handles, coordinates, exports, filters, recipes, snapshots, manifests, transactions, and PNG verification.
Plugin execution and mutation integration
gimp-mcp-plugin.py
Integrates secure transport, structured errors, composite snapshots, protected layers, stable handles, atomic exports, checkpoints, filters, and undo transactions.
Authenticated server surface
gimp_mcp_server.py
Adds authenticated transport, high-level and advanced tool surfaces, structured results, recipes, verification, checkpoints, and transaction tools.
Host CLI, diagnostics, and recipes
gimp_agent/*, gimp_agent/recipes/*, pyproject.toml
Adds the gimp-agent CLI, diagnostics, authenticated probing, JSON envelopes, exit-code mappings, recipe execution, batching, and package data.
Offline validation suites
tests/*
Adds offline coverage for security, state, exports, filters, handles, recipes, snapshots, transactions, CLI behavior, and verification.
Integration client updates
agent_edit_demo.py, bg_remove*.py, run_tests.py, scripts/*
Updates scripts to use configurable endpoints, session tokens, structured errors, and execution gating.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

  • maorcc/gimp-mcp#37: Directly overlaps with the CLI, doctor, probe, packaging, CI, and related tests.
  • maorcc/gimp-mcp#36: Overlaps with workspace orientation, state manifests, plugin integration, server integration, and tests.
  • maorcc/gimp-mcp#35: Overlaps with CI, pre-commit, project quality configuration, planner documentation, and smoke tests.

Suggested labels: documentation

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@Ryan-AI-Studios
Ryan-AI-Studios deleted the feature/0017-undo-group-transactions branch August 4, 2026 03:37
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