Behebt die fünf Befunde der Abschlussprüfung von divi-absicherung: Divi-Reiter ohne aktives Divi zeigt nur
noch einen Hinweis (kein Status, keine Prüfung, kein Aufräumen), Zustandstexte werden erst beim Rendern
übersetzt, DiviPages::setFlags() und DiviThemeBuilder::liveId(true) prüfen jetzt selbst die
Freigabesperre, WriteProbe::removeOrphans() löscht nur noch Entwürfe mit passendem Titel, und
wp lit-mcp divi-check --update-reference verweigert sich ohne Entwicklungskopie, bevor irgendetwas
geschrieben wird.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
failedOn() replaced the hint for a failure after earlier pages were
replaced, so the "Sicherung X liegt im Papierkorb" sentence of the failed
page's backup was lost. The hint now leads with it when a backup exists.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
A failed save of a library entry or Theme Builder layout now carries
restore_url when a revision exists; a partial write's hint points to the
WordPress revision screen and lit-divi-outline instead of
lit/revisions-list and lit/revision-restore, which answer not found for
these types. Pages keep the default hint.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
reason() and note() run per key and type of a body check; they now share one
offered() result per post type, so the default storage callback loads each
pod once instead of per call.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- tb-list applies the detached limit after the edit filter (reads up to 500
IDs) and notes when more are not listed (M-4); an invalid template_id is
invalid input, shared with ThemeBuilderAccess::template() (M-5).
- Templates carry their status; tb-list notes that a live template outside
publish (e.g. trashed) can only be switched off (M-10).
- changeableTemplate() refuses without canUse() first, like tb-list and
tb-create-template; the layout/template refusal difference is documented
(M-9).
- tb-create-template reads the default template from editableLiveTemplates()
(M-11); the condition-ID character set (role slugs) is documented (M-6);
tb-assign documents that a failed reattach keeps Divi's unused marks
removed (M-12 c).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
Every match carries replaceable: true only when it is identical and in a
page or post, the scope lit/library-make-global replaces; the description
and the guide say so. An excluded post type is answered like any
unavailable one, by its name (PostGuard::unavailableType()), and the
excluded list takes the Theme Builder types from DiviThemeBuilder::postTypes().
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
DiviSaver's site-wide scopes and the Theme Builder tools now share
DiviThemeBuilder::clearSiteCaches(), which clears the Theme Builder cache
even when ET_Core_PageResource is missing. lit-site-status no longer lists
et_theme_builder_clear_wp_cache twice: the Theme Builder functions row
covers it, and the post-type row uses DiviThemeBuilder::postTypes().
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
"Detached" now means for lit/tb-assign what lit/tb-list shows as detached:
DiviThemeBuilder::isListedAnywhere() looks for any _et_template row (live,
draft or Theme Builder library post). A template another Theme Builder post
lists is refused with or without reattach; nothing is written.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
lit/revision-restore takes only content types, so a write to a library entry
or a Theme Builder layout now answers with restore_url (wp-admin
revision.php for its revision_id), also per page in lit/divi-replace-text.
The guides and readme no longer present lit/revision-restore as the way back
for these types.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
VisibleEditsTest asserts the exact refusal messages (no unfiltered_html,
trash disabled) and the keepingBackup() hints for rolled-back and partial
failures with each caller's label and entry. The callers' own tests drive
GlobalEdits, ThemeBuilderEdits (through DiviWriter) and make-global with
revisions off and assert the same sentences.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
GlobalUsages gets the Theme Builder access injected as a closure
(ThemeBuilderAccess::usageState(), wired at both construction sites through
DiviIntegration::globalUsages()). Theme Builder posts are named only while
the Theme Builder is visible to the account, otherwise only counted (also
in blocked_ids); a global edit that changes them needs canUse(), a writable
"Divi Theme Builder" group and edit_post. Without an injected access the
fail-safe default checks what canUse() checks. The duplicate
THEME_BUILDER_TYPES list gives way to DiviThemeBuilder::postTypes().
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
ThemeBuilderEdits::showing() splits the live templates that show a layout
into editable ones (named under templates) and a hidden_templates count;
confirm is still decided on all of them, so a layout shown only by
uneditable templates still needs confirm. The live split is read once per
write for the confirm check and the field warnings, and field warnings now
also survive a non-confirm refusal such as the P9 backup refusal (M-12 a).
replace-text passes hidden_templates on; the write schema lists it.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- Fingerprint::content() includes non-whitespace text parts (raw HTML between
blocks, inner HTML of core blocks) and opaque blocks with all their bytes;
structure() unchanged; find-similar "identical" follows
- make-global mode 2 also compares Fingerprint::canonical() bytes of each node
- sources and targets: post types page and post only (POST_TYPES)
- a rolled-back page N>1 keeps DiviSaver's "Revision X bleibt erhalten"
- guide: escaped divi/global-layout re-expanded by Divi's do_blocks in
shortcode-module and WooCommerce text output documented as residual risk
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- library_id + targets (post_id, tree_rev, ids from lit/library-find-similar):
only nodes with the entry's content fingerprint, pages and posts only
- every target checked first (DiviWriter::page: edit_post + tree_rev, P8a;
StoredNodeGuard of the page on the instance); the entry must be an active
global entry with one readable root and no reference in any spelling (Q7)
- dry run lists pages with tree_rev, status and live flag; confirm writes each
page through DiviWriter::commit (revision, change log); live pages without
revisions get VisibleEdits' backup, refused up front where not faithful
- failure on page N: earlier pages stay replaced, N rolled back, later pages
untouched; the error names changed_posts/pages, failed_post, unchanged_posts
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
- NewLibraryEntry: spec and creation of a new library entry, shared by
lit/library-save and lit/library-make-global (NewDraft, P7, StoredNodeGuard)
- UsageMatcher::referencesAny() (ruling Q7): a global entry never names any
entry in any spelling Divi renders (P23/P24 forms, Divi 4 shortcodes inside
Divi 5 values, values casting to 0); used by library-save scope global and
make-global
- make-global: entry created, node replaced by GlobalInstance::of, page through
DiviWriter::commit; refused or rolled-back page deletes the entry, a partial
page write keeps it (the page may show it); sources are pages and posts only
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
SimilarSections compares inserted sections (not global instances) with
at most 200 editable library section entries by structure fingerprint,
read lazily once per request, only while library IDs may be named (P13).
lit/library-insert is not asked.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fingerprint::structure()/content() (E11) and lit/library-find-similar
(indirect, group Divi-Bibliothek): at most 200 posts per call (cursor),
editable entries only (own posts without edit_others_posts), contents
primed in chunks of 50, stops at 200 matches or 5000 compared nodes with
a note; library entries and Theme Builder layouts are never scanned.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Both forms Divi writes are recognized (ruling Q11): custom_meta_<key> and the
dialog form post_meta_key + select_meta_key. Choice fields get a note about the
stored value, relation fields name IDs (F4). Only templates the user may edit
are checked or named; others are counted (Q21 pattern). Warnings only, also in
the dry run of a live body. DynamicFields extracted from lit/divi-dynamic-sources.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- ThemeBuilderAccess::editableLiveTemplates() shared by tb-list and the tb-assign/tb-activate dry runs;
uneditable live templates only as a count (hidden_overlaps, hidden_live)
- tb-activate enabled:false works while the Theme Builder has a draft, with a warning
- possible_overlaps skips identical conditions; reattach records the previous enabled state;
exclude_from must be a list; tb-activate live from the read-back
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- only _et_enabled; dry run in both directions lists conditions, exclusions,
layouts, overlaps and possible overlaps (B9); confirm: true switches
- enabling needs conditions and published layouts (B10); a detached
template needs reattach first; the default template is refused
- the off-switch reaches an attached, enabled template outside publish,
e.g. in the trash (ruling Q16); result names the fast way back
- every switch in the change log; failed switch rolled back
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
- ThemeBuilderAccess::changeableTemplate(): rights (Q18 not_found), group gate,
no TB draft, never the default template, current template_rev
- omitted exclude_from stays, [] clears (Q3); live dry run shows use_on and
exclude_from before/after, overlaps and possible overlaps (B9)
- reattach only with published layouts (B10) and a live TB post; always
disabled, unmarks template and layouts; failure restores everything
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
TB layouts load through ThemeBuilderAccess (P12), live layouts (attached +
enabled, Q8) need a dry run and confirm (Q9) and get the shared restore point
of VisibleEdits, extracted from GlobalEdits (Q2: backup when revisions are
off, P9 refusals, P14 naming). divi/post-content only in body layouts (F22),
also for nested stored nodes. SaveScope::ThemeBuilderLayout sets Divi flags
and clears site CSS + TB cache.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Divi's Theme Builder page is gated by edit_theme_options; without it every
TB ID answers like a missing one. Docblocks (Q16): the wp_die guard cannot
restore WP_Hook nesting after a third-party wp_die inside a hook, and
canEditTemplate expects IDs from Divi's list.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
DiviThemeBuilder wraps Divi's Theme Builder: reads through Divi's functions,
writes layouts/templates through insert_layout/store_template behind a
wp_die guard (edit_others_posts and function checks first, every handler
filter and output buffer restored in finally), list/conditions/enabled
mirrored from Divi's own save. Template: live = attached and enabled,
whatever the post status (ruling Q8/B8). ThemeBuilderAccess: edit_others_posts
plus Divi's theme_builder role, hidden IDs answer like missing ones,
canEditTemplate (B11) and layoutsRefusal (B10). DiviCompatibility checks the
Theme Builder functions and post types (E15).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>