Releases: NertiPL/nerti-abilities-for-oxygen
Release list
0.15.1 — dwie paczki abilities na jednej witrynie kładły ją białą stroną
Fatal error: Cannot declare class ACFW_Pack, because the name is already in use
Rejestr ACFW_Pack był od początku pisany tak, żeby paczki się nim dzieliły — pierwsza deklaruje klasę, reszta ją zastaje — i miał na to strażnika if ( class_exists( 'ACFW_Pack' ) ) return;. Strażnik nie miał szansy zadziałać ani razu.
Klasa zadeklarowana bezwarunkowo na najwyższym poziomie pliku jest wiązana przez PHP na etapie kompilacji tego pliku (early binding), czyli zanim wykona się jakikolwiek kod w środku. Kiedy druga paczka kompilowała swój bootstrap.php, nazwa była już zajęta i PHP przerywało kompilację — do class_exists() nigdy nie dochodziło. Dlatego komunikat brzmi „Cannot declare class", a nie „Cannot redeclare class": to błąd kompilacji, nie wykonania.
Klasa zadeklarowana wewnątrz bloku if nie podlega early bindingowi — powstaje dopiero, gdy wykonanie do niej dojdzie. Dopiero wtedy strażnik cokolwiek znaczy.
Zmierzone 2026-08-23 na laboria.local, gdzie stoją trzy paczki z tym samym rejestrem. Na witrynie z jedną paczką usterka nie występuje, dlatego przeżyła do teraz.
Ta sama poprawka jest potrzebna w każdej innej paczce z tym rejestrem — dopóki którakolwiek deklaruje klasę bezwarunkowo, to ONA wywróci witrynę, kiedy skompiluje się jako druga.
0.15.0 — puste pole w zakładce Design to nie brak stylu
Wiedza z przeniesienia Laborii, przepisana z notatek projektu do paczki — czyli tam, gdzie agent pracujący na cudzej witrynie w ogóle ją zobaczy.
bdox/house-rules rozdział 9
Kontrolka zostawiona pusta nie wyłącza stylu — oddaje decyzję wartości domyślnej, a te są widoczne. Tabela zmierzona 2026-08-23 na żywej instalacji: kolor hoveru odnośnika, podkreślenie odnośnika, kolor przycisku, interlinia. Plus trzy rzeczy, które wypełniają się same: @media spoza zarejestrowanych breakpointów jest po cichu pomijane przy raporcie sukcesu, animacji wejścia nie zapisze edit-post (jest oxygen/set-element-animations, a offset: 0 znaczy 120 px), a insert-stylesheet zastępuje właściwości selektora zamiast je doklejać.
Dwie nowe reguły w bdox/element-defaults, obie obowiązkowe
a:hover bije twoją klasę. Globalna reguła hoveru ma specyficzność (0,1,1), płaska klasa projektu (0,1,0). Klasa wygrywa w spoczynku i przegrywa w chwili, gdy kursor dojedzie — odnośnik zmienia kolor na globalny. Objaw widać tylko pod kursorem, więc przechodzi przez przegląd. Poprawka: nigdy nie ustawiaj koloru odnośnika bez hoveru w tym samym ruchu, najlepiej przez design.text_colors.link na Section albo Div, bo to kontrolka, którą klient też widzi.
Podkreślenie odnośnika, którego nikt nie napisał. Reguła globalna daje odnośnikowi wyłącznie kolor, .bde-text-link tylko display:flex, a normalize.css Oxygena rusza w a jedynie background-color. Zostaje domyślne podkreślenie przeglądarki, niezależnie od tego, czy Modern Normalize jest włączony. Przyciski są wyjątkiem — .button-atom--* ustawiają text-decoration: none, i dlatego odnośnik „ostylowany na przycisk" ręcznie zawsze wygląda inaczej niż prawdziwy Button.
0.14.0 — Nerti Abilities for Oxygen
Wydanie o jednym temacie: żeby agent wiedział, gdzie co jest, i żeby płacił za to mniej tokenów.
Nazwa
Repozytorium i wtyczka nazywają się teraz nerti-abilities-for-oxygen. Stara nazwa unofficial-abilities-for-breakdance-elements opisywała paczkę sprzed ośmiu wydań — dziś są w niej WooCommerce, kopie zapasowe i katalog wtyczek. GitHub trzyma przekierowanie ze starej nazwy, ale slug katalogu wtyczki się zmienił: na witrynie, gdzie stała poprzednia wersja, zainstaluj nową i usuń starą.
Żeby nie trzeba było zgadywać
bdox/house-rules rozdział 8 — gdzie co siedzi w Essential Elements. Tabela zmierzona na BEFO 1.1.0.beta.4, nie wymyślona. Dwie pułapki, na których przewraca się każdy, kto zgaduje:
- padding Section siedzi w
design.spacing.padding, a padding Div i Grid wdesign.container.padding— marginesy natomiast u obu wspacing, - kolor nagłówka nie schodzi kaskadą z rodzica, bo ustawienia globalne przypisują go wprost do
h1–h6; odpowiedzią jestdesign.text_colors.headingsna Section albo Div, nie klasa CSS na wrapperze.
Plus przyciski: design.button.style to primary | secondary | custom | text, a dwadzieścia przycisków ustawionych na custom to dwadzieścia miejsc do zmiany, kiedy klient poprosi o inny odcień.
bdox/design-map z groups_only: true — dwie–trzy linie na element zamiast wszystkich kontrolek, wiele slugów w jednym wołaniu. Najpierw dowiadujesz się, GDZIE kontrolka siedzi, potem pytasz o jej wnętrze.
bdox/setup-report mówi, które grupy abilities się włączyły i dlaczego. Paczka rejestruje się po tym, co zastanie — mapa WooCommerce tylko na sklepie, kopie zapasowe tylko przy UpdraftPlusie. To jest słuszne, ale niewidoczne: agent, który nie znajduje bdox/woo-map, nie ma jak odróżnić braku wtyczki od zepsutej paczki.
Wydajność odpowiedzi
bdox/setup-report i bdox/regenerate-css nie wysypują już listingu katalogu. Witryna z 89 dokumentami buildera ma 178 skompilowanych plików CSS; to było ~6 kB JSON-a w odpowiedzi na wywołanie, które agent robi przy każdej rozgrzewce, i nie mówiło niczego poza „pliki istnieją". Teraz wraca werdykt: pliki globalne z rozmiarami, liczba plików postowych, suma bajtów i lista pustych — bo to zerobajtowy arkusz jest objawem. Pełny listing pod verbose: true.
0.13.1 — store-toolbox znowu widzi abilities kopii zapasowej
Poprawka do 0.13.0: bdox/store-toolbox sprawdzal udp_ab_definicje() — funkcje ze starego pliku piaskownicy, ktora w 0.13.0 zmienila nazwe razem z przeniesieniem kopii zapasowych do paczki. Raport meldowal backup_ability: false na witrynie, ktora te abilities ma.
0.13.0 — jeden ZIP, komplet abilities
Jeden plik ZIP na nowy projekt. Grupy abilities włączają się same, zależnie od tego, co zastaną na witrynie.
Nowe
updraft/backup-now i updraft/list-backups wchodzą do paczki. Dotąd były osobnym plikiem piaskownicy Agent Connectora, który trzeba było wgrywać ręcznie na każdej witrynie. Teraz instalują się razem z resztą i rejestrują się tylko tam, gdzie UpdraftPlus jest aktywny — tak samo jak bdox/woo-map rejestruje się tylko na sklepie.
Ta paczka nie modyfikuje UpdraftPlusa. Woła jego własny publiczny hak backupu, dokładnie tak jak przycisk „Backup Now" w panelu.
Opis backup-now mówi teraz wprost to, czego wcześniej nie mówił: przy dziesiątkach gigabajtów mediów pełna kopia idzie kilkadziesiąt minut, więc przy zmianie treści, selektorów albo ustawień globalnych właściwym zakresem jest database — kończy się w kilkadziesiąt sekund i jest prawdziwym punktem powrotu dla tej klasy zmian. Zmierzone na sklepie z ~25 GB uploads.
Zmienione
Nazwa wtyczki: „Nerti Abilities for Oxygen (Elements, WooCommerce, Backups)". Paczka dawno przestała dotyczyć samych Breakdance Elements. Slug katalogu i repozytorium zostają bez zmian — to po nich WordPress rozpoznaje aktualizacje, a przemianowanie zerwałoby je na każdej witrynie, gdzie paczka już stoi.
README ma kolejność instalacji na nowym projekcie i listę zdejmowania przed oddaniem strony. Kolejność zdejmowania nie jest dowolna: najpierw skończ budować, potem chowaj elementy przed klientem (ta sama opcja chowa je też przed agentem), potem ostatni bdox/regenerate-css, potem włącz cache stron, a dopiero na końcu usuń tę wtyczkę i Agent Connectora.
Komplet abilities w tej wersji
bdox/house-rules · bdox/design-map · bdox/woo-map · bdox/store-toolbox · bdox/element-visibility · bdox/element-defaults · bdox/setup-report · bdox/regenerate-css · bdox/get-global-settings · bdox/patch-global-settings · bdox/audit-compiled-css · bdox/merge-css-selector · bdox/builder-hidden-elements · bdox/set-image · updraft/backup-now · updraft/list-backups
0.12.1 — woo-map rejestruje sie na sklepie
Poprawka do 0.12.0: warunek class_exists( 'WooCommerce' ) wykonywal sie przy wczytywaniu pliku wtyczki, a WordPress wczytuje unofficial-abilities-... PRZED woocommerce (kolejnosc z active_plugins). Na sklepie warunek byl falszywy i bdox/woo-map po cichu nie powstawala. Sprawdzenie przeniesione na hak wp_abilities_api_init z priorytetem 5.
0.12.0 — kazda ability wolana bez argumentow, i sklep opisany tam, gdzie sie go buduje
Zmierzone na Oxygen 6.2.0-beta.6 + Breakdance Elements for Oxygen 1.1.0.beta.4 + Breakdance WooCommerce for Oxygen 1.1.0.beta.1, WordPress 7.1, PHP 8.1.34.
Naprawione — dotyczyło każdej ability w paczce
mcp-adapter-execute-ability z parameters: {} dochodzi do WP_Ability::execute() jako null, nie jako pusty obiekt. execute() woła najpierw normalize_input() (podstawia input_schema['default'], gdy wejście jest nullem), a dopiero potem validate_input(). Bez zadeklarowanego default null przechodzi normalizację nietknięty i walidacja odrzuca go komunikatem „input nie jest typu object".
Skutek: bdox/regenerate-css, bdox/setup-report, bdox/element-visibility i bdox/builder-hidden-elements nie dawały się wywołać tak, jak każe ich własny opis — bez parametrów. Poprawka siedzi w bdox_pack_ability(), więc obejmuje też każdą ability dopisaną później.
Nowe
bdox/woo-map— atlas elementów sklepu: czym każdy jest, kiedy po niego sięgnąć i jakie grupy z zakładki Design ma, czytane na żywo ze schematu. Rejestruje się tylko, gdy Breakdance WooCommerce for Oxygen jest aktywny. Niesie zasadę, która oszczędza najwięcej pracy: ustawienia globalne mają całą gałąźwoocommerce(przyciski, kolory, pola formularzy, plakietka promocji, gwiazdki, komunikaty, tabele, skala odstępów i typografii), która ubiera cały sklep jednym zapisem — zanim ktokolwiek dotknie pojedynczego elementu.bdox/store-toolbox— które wtyczki są potrzebne przy sklepie, które już tu są, których brakuje, i dwie, których nie wolno włączać przy pracującym agencie: wtyczka bezpieczeństwa blokująca REST API i cache stron pokazujący poprzednią wersję strony.
Zmienione
bdox/design-mapzwija bloki typografii i efektów tekstu do jednej linii.EssentialElements\Wooproductpricemiał 70 linii mapy, w większości dwa razy to samo (osobna typografia ceny bieżącej i przekreślonej) — teraz ma 8.expand: trueprzywraca pełne rozwinięcie.bdox/house-rules— rozdział 6 (trzy poziomy stylowania sklepu) i 7 (wtyczki).- Liczby przemierzone: 188 zarejestrowanych elementów, 155 widocznych dla MCP bez paczki, 165 z paczką. Paczka odzyskuje na tej wersji 10 elementów, nie 13 —
Section,HeadingiIconsame zeszły ze stałejBREAKDANCE_MCP_HIDDEN_ELEMENTS.
0.8.1 — setup-report reads the font the browser got, not the one you sent
Added
-
bdox/setup-reportnow reports typography as the browser resolves it, read from the compiledglobal-settings.cssinstead of the stored settings tree, with a verdict. Two things fail silently when written and neither shows a symptom in the builder:- A Google Font slug is
strtolower(preg_replace('/[^a-zA-Z0-9]+/', '', $family))(plugin/fonts/integrations/google-fonts/google-fonts.php:110) — every non-alphanumeric character is dropped, not hyphenated.gfont-bricolage-grotesqueis therefore accepted, stored, and emitted verbatim as thefont-family, so the font never loads and every heading falls back to the generic. Measured 2026-08-21 on 6.2.0-beta.5:--bde-heading-font-family:gfont-bricolage-grotesquein the compiled file whileset-global-settingsreported success. The correct slug isgfont-bricolagegrotesque. A single-word family such asgfont-interresolves fine, which is exactly why the mistake survives — it only bites on multi-word names. typography.base_sizetakes effect only in the flat{number, unit, style}shape; the breakpoint map the built-in schema demands validates and does nothing, because the twig reads.style.
The verdict says
unresolved_font_slug in heading_font(naming which keys) orok.testy/sprawdz-typografie.phpcovers both branches plus later-declaration-wins and the missing-file case —wp eval-file, six assertions, no framework. - A Google Font slug is
Changed
bdox/patch-global-settingsdescription namestypography.base_sizeas the second confirmed key the built-in tool cannot write usefully, and warns about the follow-on: oncebase_sizeis stored flat, lateroxygen/set-global-settingscalls fail their output validation (base_size[number] is not of type object,null) although the write itself went through. Read state back withbdox/get-global-settings. Same root cause asbuttons.primary.corner_radius— the builder stores flat, the MCP schema demands a breakpoint map.
0.8.0 — the option that hides elements from the client also hides them from the agent
Nothing added, nothing removed. Every ability description, the plugin header, the README and UPSTREAM.md were re-measured against Oxygen 6.2.0-beta.5 + Breakdance Elements for Oxygen 1.1.0.beta.1, WordPress 7.1, PHP 8.2.29 and corrected. Three of the pack's stated reasons for existing turned out to be fixed upstream, one was flatly wrong, and one new coupling was found.
Fixed
- The pack claimed
oxygen_builder_hidden_elementsdoes not affect MCP. It does. The plugin header, the README andbdox/element-visibility's description all said the option controls the editor panel only.admin/settings-page/tabs/elements.phphangsfilter_builder_elements()on thebreakdance_builder_elementsfilter at priority 10, andmcp/schemas/elements.phpruns the MCP element list through that same filter. Measured: addingEssentialElements\Buttonto the option tookoxygen-get-element-slugsfrom 164 to 163 and madeget-element-schemasrefuse it; removing it restored 164. Rule that follows, now stated in three places: build first, hide last. bdox/builder-hidden-elementsreported a number that never moves. It returnedbuilder_panelfromcount(get_elements_for_builder()), which maps over every registered classname and only feeds the filtered list toaddPanelRules— measured 165 both before and after hiding an element. Replaced withmcp_visible_countandhidden_from_mcp, so the ability now reports both sources of truth: the stored option and what MCP can actually address.- The "empty list is repopulated on the next request" claim was wrong. Measured: an empty
builder_hidden_elementspersists across requests.addDefaultHiddenElements()is called fromhandleVersionChange()and the setup wizard, so the re-fill happens on the next Oxygen update, not the next request. The non-empty placeholder is still correct — the reason changed, not the behaviour. - The element counts in the header and README were from beta.2 (162 / 149). Re-measured: 186 registered, 151 MCP-visible without the pack, 164 with it.
BREAKDANCE_MCP_HIDDEN_ELEMENTSnow holds 14 entries and no longer bansSection,HeadingorIcon— those three are hidden purely by the WP option.
Changed
bdox/merge-css-selectorno longer claims to be the only route to!important. Oxygen fixed that in 6.2.0:css-to-properties.phpdiverts every!importantdeclaration intocustom_csswith the flag intact, before the typed converters run. Measured on beta.5 —.probe{color:#ff0000 !important;padding:8px}stored padding as a typed property andcustom_cssas:selector {\n color: #f00 !important;\n}. The ability stays for the two things still broken: the importer replaces a selector's whole property map per breakpoint (measured — amargin-only import wiped bothpaddingandcustom_css), and it lowercases custom-property names (--myVarstored as--myvarwhilevar(--myVar)keeps its case, so the reference dies and the import reports success).bdox/patch-global-settingslost its main reason and kept a smaller one.set-global-settingsdeep-merges since beta.5 (breakdance_mcp_deep_merge_settings) — measured, atypography.base_font_size-only call leftcolors.paletteandtypography.body_fontintact. What it still cannot do is write a key on an object closed withadditionalProperties: false:buttons.primary.background_hovergoes through,buttons.primary.typography.color_hoveris rejected — andelements/macros/atom-v1-button-css.twigreads exactly that key. The description now says so instead of advertising the merge.bdox/get-global-settingsstays, with the real failure. Soflyy fixed the empty-settings case ({"settings":{}}instead of an error), so on a blank site the built-in reader works. On a real one it still returns nothing:output[settings][buttons][primary][corner_radius][unit] is not of type object,null. Observed on a production site and reproduced on the beta.5 lab install with the same stored value. The output schema wantscorner_radiusbreakpoint-keyed; the builder stores it flat as{number, unit, style}— and stores it breakpoint-keyed underbutton_presets[].styles, so the same control is persisted two different ways.bdox/regenerate-cssnarrowed its claim. Still no cache-regeneration tool among the 49 the beta.5 server exposes, but Oxygen's own save paths do regenerate (data/save.php:121callsgenerateCacheForPost();save_global_settings()andsave_selectors()callgenerateCacheForGlobalSettings()). The ability is for data changed outside those paths, and for a stale compiled cache.bdox/element-visibilitywas rewritten to report three lists, not two counts.banned_by_oxygen(the constant),hidden_in_elements_panel(the WP option),restored_by_this_pack, plusstill_hidden_from_mcpand an explicit warning about the shared filter. It also stopped comparing element slugs against classnames, which made the oldhidden_from_mcpmeaningless.- The two
add_filtercalls stay, with the deletion condition written into the code. They exist only because the fundamentals are supposed to replace these elements — and on BEFO 1.1.0.beta.1 the fundamentals do not exist:class_exists()isfalseforFText,FImage,FRichText,FTextLink,FSvgIcon2,FHtmlCodeandEssentialElements\ContainerLink. The nativeOxygenElementsfallbacks exist but have no Design tab — measured viaoxygen-get-element-schemas:EssentialElements\{Section,Heading,Text,Image2,Button}exposedesign,OxygenElements\{Container,Text,Image}do not. The header now names the re-measure condition: after BEFO ≥ 1.1.0.beta.3, checkclass_exists('EssentialElements\FText')and whether its schema has adesignsection; only if both hold do the filters get deleted. bdox/set-imagere-measured, unchanged. Thewpmediacontrol still schemasmediaas{id, url, alt}withadditionalProperties: false, and bothOxygenElements\ImageandEssentialElements\Image2still resolvesrcascontent.image.media.sizes[size].url.typography.css.twiglines 114 and 126 still lack| join(' '), sotext-decoration-linestill compiles to the literalArray. Recorded in UPSTREAM.md as still open.
The cost of the restore is now written down
Previously unstated: restoring on breakdance_builder_elements also unhides those 13 elements in the builder's Add panel, because get_elements_for_builder() hands the same filtered array to FilteredGets\addPanelRules(), which sets alwaysHide on whatever is missing from it. Measured — pack active: Section, Div, Heading report no alwaysHide; pack filter removed: all three do. Two consequences, now documented in the plugin header, the README and bdox/builder-hidden-elements:
- While the pack is active the client sees those elements too, which removes exactly the simplification Oxygen was going for.
- A human who hides one of the 13 in Oxygen → Settings → Elements is silently overruled: the pack restores at priority 20, after the settings page subtracts at priority 10.
Restoring "for MCP only" was considered and rejected. The panel and MCP go through different functions but share one filter, and the filter carries no caller context, so the only discriminator is the admin-ajax action name — a string Oxygen may rename, after which the guard silently stops matching. Instead, the existing bdox_pack_restored_elements filter is documented as the lever: add_filter( 'bdox_pack_restored_elements', '__return_empty_array' ) at handover. Handover order, which is not the build order: build → hide → narrow (or deactivate). Hiding while the pack still restores does nothing.
0.7.0 — media-library images that render
Added
-
bdox/set-image— point an image element at a media-library attachment so it actually renders, at a named size and with asrcset. The built-in path cannot do this. Measured on Oxygen 6.2.0-beta.2: anOxygenElements\Imagewithfrom: media_libraryandsize: "large"renders the builder's 540×540 grey placeholder whileedit-postreports success and reads the data back exactly as written. The element resolves itssrcascontent.image.media.sizes[size].url, but the MCP schema declaresmediawith onlyid,url,altandadditionalProperties: false, sosizescan never be written and the lookup falls through to|default().attributes.srcsetis unreachable the same way, so an API-created image emits nosrcsetat all.Measured end to end on a probe page: before,
src="data:image/svg+xml…"and one placeholder; after,src="…-1024x640.png"with a five-candidatesrcsetand zero placeholders. An unknown size is the one remaining way to get a placeholder, so it is rejected with the list of real sizes.altneeded its own handling. The element does not rendermedia.altfrom the tree — its template readsget_attachment_alt(media.id)infrom_media_librarymode andcustom_altincustommode, so an attachment without_wp_attachment_image_altrenders an<img>with noaltattribute at all. Passingaltswitches the element to custom mode, andalt_modein the response says when the attachment's own alt is empty.Upstream report: soflyy/agent-connector-for-wp#79
Changed
- New helpers
bdox_pack_get_tree()/bdox_pack_save_tree()/bdox_pack_map_node()._oxygen_datais not the tree — it is an object whose single keytree_json_stringholds the tree as an encoded string, so decoding one level and subscripting['root']yields null.map_nodeis copy-based rather than a reference finder: an aliasing finder previously duplicated whole subtrees across seventeen pages.