Version 2.1.1
June 19, 2026
Maintenance release — no functional changes from 2.1.0.
Version 2.1.0
June 19, 2026
Reworks the Reviews dashboard into a native Craft index and tightens the review queue.
Added
- The Reviews dashboard (
/admin/delta-reviews) is now a native Craft element-style index: a left source sidebar (Awaiting my verdict / My submissions / All reviews, each with a count badge) drives a single sortable, searchable, paginated table, replacing the three stacked tables.
Changed
- Awaiting my verdict now lists only reviews still awaiting your verdict (pending in the current round), so it matches the control-panel nav badge.
- The actionable queues (Awaiting my verdict / My submissions) hide concluded reviews (published / declined / withdrawn); the admin All reviews source keeps the full audit history.
- The Status column sorts by workflow state rather than by the localized label text.
Fixed
- Reviewer pills stay on a single line and truncate long names with an ellipsis (full name on hover) instead of wrapping into a multi-line blob.
Performance
- Dashboard rows batch-load their entry titles in a single query instead of one lookup per row, and the table fetches only the requested source bucket instead of computing all three.
Version 2.0.0
June 18, 2026
Major release: adds an inline Review Mode and a multi-reviewer submit-for-review workflow on top of the v1.x diff viewer.
Added
Review Mode
- Accept or reject individual changes on the review page, then publish only the accepted changes to the canonical entry as a new revision. Per-field and per-Matrix-block granularity, with block reordering as its own decision.
- Keyboard-driven stepper (
J/Kto navigate,A/Rto decide). Decisions persist in browserlocalStorageand resume across restarts; stale-state detection against the canonical entry'sdateUpdatedguards against mid-review edits. The cursor highlight only appears once you start navigating, so the diff isn't pre-highlighted on load. - An Also delete source draft option (off by default) when the source is a draft — publishes, then deletes the draft. Left unchecked, the draft persists as a queue of the changes that weren't accepted.
MergeServiceowns all write logic — atom validation against a fresh diff, field/Matrix apply, a singlesaveElementfollowed byapplyDraftfor atomic publication.DiffController::actionApplyendpoint with structured error codes (no-changes,source-not-found,stale-atoms,validation-failed).Enable Review Modesetting (default on) as a kill switch.
Submit-for-review workflow
- Authors submit a published draft to one or more reviewers. Reviewers Approve or Decline (with an optional note emailed to the author). To request changes, a reviewer leaves a comment — there is no separate "request changes" verdict.
- A configurable approval policy decides when a review passes: any one reviewer (default), all assigned reviewers, or at least N (clamped to the number assigned).
- Reviews happen on a dedicated full-page workspace at
/admin/delta-review?reviewId=N: reviewer roster + round, verdict actions, the diff with inline (GitHub-style) anchored comments, a general discussion, and — for reviewers who can apply — always-on per-change accept/reject with a live "decided" counter and Apply N accepted. The diff slideout and thedelta-comparepage are diff-only and link to the review page ("Open review"). - A live draft preview renders beside the diff on the review page for sections with front-end URLs (a tokenized render of the draft). Open it full-width in a new window, hide it per reviewer (remembered across reviews), or turn it off globally with the Enable Preview setting.
- A submitted draft isn't locked: the author can keep revising it (reviewers see the updated diff), withdraw an active request (re-submitting re-opens it in a new round), or the review is finalized by a verdict. Decline is terminal.
- Publishing an approved review — immediately, or scheduled for later via a queued job and Craft's native date + time picker — requires the
craftdelta-applyReviewpermission and Craft's native save permission on the entry, so a review-only role can't push content live. A schedule is rescinded automatically when the review leaves the approved state (declined/withdrawn) or its draft is deleted. - A Granular review path: Review Mode on a submitted draft; applying accepted atoms publishes them and closes the review (a partial apply finalizes the review; see the README).
- A Reviews dashboard in the CP nav (awaiting your verdict / your submissions / all for admins), and a Workflow status column on entry index pages (In review / Approved / Approved — scheduled / Declined / Withdrawn / Published).
- Review comments: general or diff-atom-anchored, with one level of replies, resolve/unresolve, and automatic outdated detection against the live diff. Posting a comment notifies the other side (author ↔ reviewers), debounced so a burst sends at most one email per recipient per review (
workflow/comment,workflow/resolve-comment,workflow/thread). - Three general (section-agnostic) permissions under Craft Delta: Submit drafts for review (
craftdelta-submitDraft), Review submitted drafts (craftdelta-reviewDraft), and Apply review-mode changes (craftdelta-applyReview). Which sections a user can act on is governed by Craft's native section permissions; the reviewer picker lists only users who can view peer drafts in the draft's section. - Email notifications on every transition (submitted, approved, declined, published, scheduled-publish, and new comment), each sent in the recipient's preferred language. The five templates are overridable from
config/craft-delta.php(emailTemplates) — map any ofsubmitted/approved/declined/published/commentto your own site template; an unmapped or missing template falls back to the bundled default. WorkflowServiceevents for third-party integration:EVENT_AFTER_SUBMIT,EVENT_AFTER_APPROVE,EVENT_AFTER_DECLINE,EVENT_AFTER_WITHDRAW,EVENT_AFTER_PUBLISH— each carrying theReviewmodel as$event->review.Enable Workflowsetting (default on) as a kill switch covering both the UI and the endpoints.
Other
MatrixDifferemits each change's canonicalblockUidso atom keys round-trip across canonical / draft / revision.- Translations across all 8 supported locales (English, German, Spanish, French, Italian, Dutch, Polish, Portuguese).
- A bundled
config.phpdocumenting every setting (all overridable per-environment viaconfig/craft-delta.php) and the variables each email template receives. - PHPUnit coverage for atom parsing, validation, the Matrix merge/order algorithm, the workflow state machine, and the approval policy.
Changed
- Schema version is
2.1.3. The upgrade migrations create three tables:craftdelta_reviews,craftdelta_review_reviewers, andcraftdelta_review_comments. Reviews survive publication as audit records (reviews.draftIdis nulled when the draft is applied and deleted). - Applying changes (Review Mode or the workflow's Granular review) requires the dedicated Apply review-mode changes (
craftdelta-applyReview) permission; edit/save permissions alone are not sufficient. Admins have it implicitly. - The full-page compare view moved to the
delta-compareCP URL so it no longer requires the Access Craft Delta plugin permission (the oldcraft-delta/compareURL still resolves).
Security
- Publishing an approved review requires the
craftdelta-applyReviewpermission, matching the granular Review-Mode apply path — native entry save rights alone are no longer sufficient. Verified: a user with section save rights but withoutapplyReviewis rejected (403) atworkflow/publish;applyReviewholders and admins are unaffected.
Fixed
- A reply no longer shows a "Reply" affordance (the data model supports only one level of replies), which previously dead-ended in a generic "could not be saved" error.
- Closed/terminal reviews (published, declined, cancelled) render comments read-only — the composer, reply, and add-comment affordances are hidden, since the backend rejects posts on an inactive review.
- Review UI polish. Non-primary buttons no longer use the CP accent color — "Approve" reads as green and "Decline" as red, rather than the install's accent. "Submit comment" is a quiet right-aligned button rather than a full-width CTA. Zero-change reviews no longer render an "Apply 0 accepted" toolbar. The reviewer picker is a styled checkbox list instead of a raw native multi-select. Scheduling uses a native date + time picker instead of a free-text prompt.
Compatibility
- No breaking changes for users without workflow permissions — the v1.x read-only diff slideout and Compare Revisions button behave identically.
Upgrading from a 2.0.0 pre-release
- The pre-release "Request changes" verdict and the re-request / review-rounds loop are gone. Reviewers now Approve or Decline only; requests for changes are expressed as comments. An in-flight
changes_requestedreview is reopened by the schema2.1.3migration (→open, reviewer verdicts reset to pending) so existing rows aren't stranded. - Workflow permissions are no longer scoped per section. If a pre-release granted
craftdelta-*:<sectionUid>keys, those are obsolete — re-grant the three general permissions and manage section access through Craft's native section permissions. - The pre-release single-reviewer
craftdelta_draft_workflowstable is dropped and replaced by the reviews tables; pre-release workflow rows are not migrated.
Version 1.1.0
April 15, 2026
Added
- Asset relation diffs now render thumbnails, filenames and metadata (dimensions, file size) instead of bare titles.
- Sticky tab headers and a jump-to-section navigation bar at the top of the diff, with a live highlight of the section currently in view while scrolling.
- "Tab:" prefix on tab headers and jump-nav items so it's always clear what kind of section a heading refers to.
Changed
- Diff colors are now stable across selection changes. Comparisons are always sorted chronologically server-side, so additions stay green and removals stay red regardless of which version sits in which dropdown. The redundant swap button has been replaced with a static arrow indicator.
Fixed
- Relation diffs inside unsaved Matrix sub-fields no longer leak raw element IDs ("+ 900") into the rendered output.
RelationDiffernow hydrates raw integer IDs and handlesElementCollectionvalues from Craft 5's eager-load path. RelationDiffer::indexByIdno longer crashes on transient elements with a nullid.
Tests
- Added
RelationDifferTestwith 20 unit tests covering null/empty inputs, set-difference logic, HTML escaping,ElementCollection, raw-ID hydration, and the null-id guard. Five Asset rendering tests are explicitly skipped pending a Craft kernel test bootstrap.
Version 1.0.0
March 2, 2026
- Initial release