Recent Activities

This page shows what are we working on.

breezefront / theme-frontend-breeze-enterprise-eir

6 hours ago success
  • head
    • Update favicon color 5ea666

    • Update favicon 18d8dc

    • Slightly update footer background. 5fcbfc

    • Footer content update. Add contact block (#3) dea42e

    • Fixed missing minicart overlay on first open (#2) 54feaa

    • BCB homepage: updated Browse categories block dbfa89

    • Breadcrumbs 196469

    • Done with search (#2) d8e0f3

    • Enhance minisearch functionality with slideout behavior and styling adjustments without Ajaxsearch (#2) 8c4a9d

    • Minisearch styles when ajaxsearch disabled... in progress (#2) 259fac

    • Remove unused styles from viewcart action and update empty subtitle styles in minicart (#2) dba7a5

    • Minicart complete (#2) 56efd2

    • Search on desktop (#2) 9c587e

    • BCB homepage: added videos section 7ee864

    • Minicart inprogress (only buttons to adjust)... (#2) c1be91

    • Minicart update in progress.... c3d18b

    • Minicart update in progress... (#2) 55e7b9

    • INstaller. Create dummy CMS block header_panel_info to allow user add custom content (#2) f70d58

    • Adjust minicart counter (#2) 03e843

    • BCB homepage: Added brand logos section b905f1

    • BCB homepage: Added testimonials section 2ab2cf

    • Update newsletter styles: adjust input border and add consent positioning (#2) 02d37d

    • Header. Update search behaviou and look of the result dropown. 993432

    • BCB homepage: Added FAQ a0bfde

    • Add focused search styles. d80f88

    • BCB homepage: added new sections 875068

    • BCB homepage: added ECI and full-width banner d40cfa

    • Top navigation added. 8fa9a3

    • Remove color from menu links dec081

    • Clone currency and store switchers in header slideout menu for improved functionality de36e3

    • Enhance header and newsletter styles for improved layout and responsiveness in header slideout menu. b63dd0

    • Installer. Update header slideout menu styles. 825795

    • Update footer top content HTML to enhance newsletter section styling.
      Don't set font familiy for header in Page Builder ba0b81

    • BCB homepage WIP b228af

    • Basic navpro slideout styles 75ac0e

    • Refactor header slideout menu and newsletter styles for improved layout and consistency 3b42ff

    • Header slideout menu... d4f174

    • Listing styles for the list mode and old price update. cbff61

    • Update README.md to clarify usage of `with-bottom-divider` CSS class and provide detailed instructions 1b9ea5

    • Pagination and make with-bottom-divider general. 37ea17

    • Added list banner 5 config; updated installer, moved it to json a43985

    • Add new layout configuration and remove easybanner references; update footer content and styles 87165b

    • Refactor easybanner configuration and installer for product listing banners 8b1d0d

    • Installer. Listing grid banner added. 914c01

    • Add swatches variables and layout styles d59581

    • Update positioning for filter title and content in layered navigation 8cbd21

    • Add image dimensions for product listings and related widgets in view.xml 6985cd

    • layout and styles for category view, product toolbar, shop by button 08fd27

    • Add layered navigation styles and update imports 944ff1

    • Keep working on prodcut listing and category page. 411088

    • Keep working on product listing toolbar. ebcfac

    • Working on product listing and toolbar look. 1ab39d

    • Add Cooper* font 132906

    • Add listing item styles and variables e725b5

    • Product lisnting in progress - grey bg and border radius. 4e7c35

    • Add new variable files for colors, typography, header, footer, icons, navigation, popover, minisearch, and gradient ba122c

    • Refactor footer and newsletter styles for improved consistency and responsiveness d831e4

    • Footer top newsletter - some updates. 452ca5

    • Add footer top content block and styles for newsletter integration (WIP) 128131

    • Footer bottom. 8d58ea

    • Add footer content block and styles for enhanced footer layout 4d6b1b

    • Header. Hide menu on medium screens. Update search look on monile. e0146d

    • Installer. Add navigation slideout menu a89fd5

    • Add EasySlide functionality for header panel with custom slides and styles e55b0b

swissup / theme-frontend-argentohyva-stripes

10 hours ago error

breezefront / module-breeze-ai

13 hours ago success
  • head
    • feat(content-builder): generate an image where the design has only a placeholder (#93) (#100)

      * feat(image): tell a wireframe stand-in from a flat design (#93)

      PlaceholderDetector cannot be the trigger for generating a picture, and the
      reason is what its answer costs. There, a false positive keeps the
      dummyimage.com URL the build already used; in front of generation, a false
      positive paints an invention over a band a designer meant to be flat — a
      brand-coloured hero, a dark call-to-action strip — and bills for it. So the
      question has to be a different one, asked of positive evidence: not "is this
      crop empty" but "is this a wireframe at all".

      Answered of the whole screenshot, once per build, because a grey box in a mock
      and a grey box in a design are indistinguishable at the size of one crop. Two
      signals have to agree: chroma, which a design's photography or brand colour
      pushes up, and luminance entropy, which is what stops a black-and-white
      photographic design being read as a mock. A crop's own drawn marks — a cross,
      an outlined frame — are the second way in, for the design that is finished
      apart from the one band still holding a box.

      Measured against real files: this module's five-band mock lands at chroma 0.014
      and entropy 1.9, a storefront screenshot with photography at chroma 0.32, a
      photograph at entropy 5.1.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * feat(content-builder): draw the picture a wireframe left a box for (#93)

      The other half of issue #85. Extraction answers a screenshot of a real design
      and answers nothing at all for a wireframe, where the region genuinely is a grey
      box and the merchant replaces the placeholder by hand.

      Second, not first, and the order is the point: extraction is free and exact,
      while one generated image costs $0.01 to $0.25 against about $0.03 for the whole
      text build that placed it. So generation runs only where extraction has already
      declined, and only where a prop passes every gate — the setting is on, the prop
      is a band's main image rather than an icon, the build call itself described a
      missing picture there, and WireframeDetector agrees the reference is a stand-in.
      Off by default, with a hard per-build cap that is a spend limit rather than a
      tidiness one, hence no "unlimited" at zero.

      The descriptions ride back on the build call like the regions do, so this costs
      no request of its own. An image model is configured on its own — Claude
      generates no images, so the text model says nothing about who can draw one — and
      lives in its own pool rather than as a row that could become the default a chat
      call routes to.

      Nothing here can cost the build: a refusal, a timeout, a missing key, a full
      disk or the cap each leave the dummyimage.com placeholder in place and say so in
      the build note, one note per prop rather than two contradicting each other.
      Every call that answered is written to the usage ledger as kind=image, priced
      through the same table the admin's pre-build estimate is priced through, so a
      page's cost is complete exactly where it is largest.

      The crop is deliberately not sent as a reference image. Under these gates it is
      the wireframe's own grey box: nothing to imitate, and billed as input. Its shape
      is used instead, to pick the size.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * feat(admin): say what a build may spend on images before it starts (#93)

      A ceiling, not a forecast, and it cannot be otherwise: how many pictures a page
      needs is only known once the build call has answered, since the descriptions
      ride back on it. So the modal and the editor's chat panel show the most the run
      can cost — the cap times the rate — which is the number the cap exists to make
      true. Priced through the same ImagePrice the ledger writes, so the estimate and
      the invoice cannot disagree.

      One sentence, composed once and shared by both controls, which compose their own
      config JSON and would otherwise drift apart.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * fix(content-builder): a free image rate is not an unknown one (#93)

      The page total read "cost is not known" off the numeric total rather than off
      whether a rate was found, so a store on a zero per-image rate — an internal
      proxy, a plan with images included, the override set to 0, all of which
      Helper\Config deliberately accepts — was told its pictures cost an unknown
      amount instead of nothing. Gate the wording on costKnown, which is the thing
      that actually tracks it.

      While there: an amount under a cent is written with four places rather than two
      in both the build note and the pre-build estimate. Two writes $0.0040 as $0.00,
      which in this line reads as "the picture was free" — the same claim Usage\Cost
      keeps its own precision to avoid.

      Reported by Copilot on PR #100.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * fix(image): recognise OpenAI's key and rate-limit errors by their wording (#93)

      A live run against the real endpoint with a deliberately bad key came back as
      "OpenAI image error: Incorrect API key provided: sk-…", not as the intended
      "invalid image API key. Check configuration." The SDK raises its own exception
      carrying the API's message body and nothing else, so a check for '401' never
      matches — the one failure an admin can act on was reported as a generic error.

      Match the wording as well as the status, and the same for the rate limit.

      Model\Provider\OpenAi::handleException() has the identical blind spot for chat
      calls. Left alone here: it is not this issue's code, and the fix belongs with a
      run that observes it the same way this one was observed.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * fix(content-builder): stop telling the model a stand-in is already handled (#93)

      A live run explained the silence. With generation on, every gate open and the
      description rules in the prompt, a small model returned no image_prompts at all
      on a wireframe — because the region rules, which sit closer to the coordinates
      it was writing, ended with "leave those props out of image_regions and let the
      placeholder rule above fill them". A model that believes a prop is taken care of
      has no reason to describe it.

      So that clause now has two versions and the build picks by whether anything will
      draw the picture: point at the placeholder when nothing will, and at
      image_prompts when something will, naming the consequence of saying nothing. The
      ask itself is stated as a requirement rather than as an offer for the same
      reason.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * fix(image): address 5 Copilot review issues on PR #100 (#93)

      - Gemini: catch ConnectException before it bypasses handleException and
      leaks ?key= credential in server log (ConnectException is not a
      RequestException subclass)

      - WireframeDetector: convert palette/indexed images to truecolor before
      per-pixel sampling; imagecolorat() returns a palette index on GIF and
      indexed PNG, not packed RGB, so a coloured palette image was read as
      achromatic and misclassified as a wireframe

      - PromptBuilder: REGION_STAND_IN_RULE_GENERATING now asks the model to
      still report image_regions for stand-in props (for shape/mark
      detection) and describe them in image_prompts — the previous wording
      told the model to omit the region, making the crop-marks gate
      unreachable for isolated placeholders in finished designs

      - ImageExtractor: take a crop in memory when extraction is off but
      generation is on and the page is not already a wireframe, so the
      crop-marks gate works in generation-only mode; skip the crop when the
      wireframe verdict already covers the whole page

      - ImageExtractor/ImageGenerator: track billable API attempts separately
      from successful saves; a storage failure after the provider answered
      no longer reopens a generation slot above the admin-configured cap

      * fix(test): replace assert() with assertNotFalse() — assert() forbidden by Magento CS (#93)

      * fix(image): address 4 more Copilot review issues on PR #100 (#93)

      - ImageResponseException: new exception subclass for 'provider answered
      but no image' (HTTP 200, refusal, bad base64) — distinct from
      LocalizedException so ImageGenerator can count it as billed without
      treating every auth rejection and rate-limit error as billable too

      - ImageGenerator: catch ImageResponseException as billed (writeImage +
      billed=true); catch everything else as not-billed (provider never
      reached); mb_substr/mb_strlen for multibyte prompt truncation so a
      multilingual description is not split mid-codepoint

      - PromptBuilder: IMAGE_PROMPT_RULES last item rewritten — stand-ins get
      both image_regions (shape/mark detection) AND image_prompts
      (description); the 'never both' rule was directly contradicting the
      REGION_STAND_IN_RULE_GENERATING that this PR introduced

      - ImageExtractor: add 'placeholder' flag to attempt struct so
      reportUnfilled() can distinguish 'PlaceholderDetector rejected this
      crop' from 'cropBytes() took a crop for stand-in detection only';
      the old attempt['crop'] !== null check was true for both and falsely
      told the admin the reference showed a placeholder on any non-wireframe
      page where generation declined for a different reason

      * fix(openai): HTTP fallback for PHP 8.1 + openai-php 0.10 (#93)

      openai-php 0.10 (the only version PHP 8.1 can install) throws a
      TypeError when hydrating gpt-image-1's base64 response. The paid
      API call was wasted. Bypass the SDK and call the REST endpoint
      directly via Guzzle so the call still produces an image.

      ---------

      Co-authored-by: Claude Opus 5 <noreply@anthropic.com> c6926a

    • fix(openai): HTTP fallback for PHP 8.1 + openai-php 0.10 (#93)

      openai-php 0.10 (the only version PHP 8.1 can install) throws a
      TypeError when hydrating gpt-image-1's base64 response. The paid
      API call was wasted. Bypass the SDK and call the REST endpoint
      directly via Guzzle so the call still produces an image. d675d0

    • fix(image): address 4 more Copilot review issues on PR #100 (#93)

      - ImageResponseException: new exception subclass for 'provider answered
      but no image' (HTTP 200, refusal, bad base64) — distinct from
      LocalizedException so ImageGenerator can count it as billed without
      treating every auth rejection and rate-limit error as billable too

      - ImageGenerator: catch ImageResponseException as billed (writeImage +
      billed=true); catch everything else as not-billed (provider never
      reached); mb_substr/mb_strlen for multibyte prompt truncation so a
      multilingual description is not split mid-codepoint

      - PromptBuilder: IMAGE_PROMPT_RULES last item rewritten — stand-ins get
      both image_regions (shape/mark detection) AND image_prompts
      (description); the 'never both' rule was directly contradicting the
      REGION_STAND_IN_RULE_GENERATING that this PR introduced

      - ImageExtractor: add 'placeholder' flag to attempt struct so
      reportUnfilled() can distinguish 'PlaceholderDetector rejected this
      crop' from 'cropBytes() took a crop for stand-in detection only';
      the old attempt['crop'] !== null check was true for both and falsely
      told the admin the reference showed a placeholder on any non-wireframe
      page where generation declined for a different reason 362f3d

    • fix(test): replace assert() with assertNotFalse() — assert() forbidden by Magento CS (#93) 4ad84b

    • fix(image): address 5 Copilot review issues on PR #100 (#93)

      - Gemini: catch ConnectException before it bypasses handleException and
      leaks ?key= credential in server log (ConnectException is not a
      RequestException subclass)

      - WireframeDetector: convert palette/indexed images to truecolor before
      per-pixel sampling; imagecolorat() returns a palette index on GIF and
      indexed PNG, not packed RGB, so a coloured palette image was read as
      achromatic and misclassified as a wireframe

      - PromptBuilder: REGION_STAND_IN_RULE_GENERATING now asks the model to
      still report image_regions for stand-in props (for shape/mark
      detection) and describe them in image_prompts — the previous wording
      told the model to omit the region, making the crop-marks gate
      unreachable for isolated placeholders in finished designs

      - ImageExtractor: take a crop in memory when extraction is off but
      generation is on and the page is not already a wireframe, so the
      crop-marks gate works in generation-only mode; skip the crop when the
      wireframe verdict already covers the whole page

      - ImageExtractor/ImageGenerator: track billable API attempts separately
      from successful saves; a storage failure after the provider answered
      no longer reopens a generation slot above the admin-configured cap 403bca

    • fix(content-builder): survive an unescaped widget type (#91) 2df025

    • fix(content-builder): stop telling the model a stand-in is already handled (#93)

      A live run explained the silence. With generation on, every gate open and the
      description rules in the prompt, a small model returned no image_prompts at all
      on a wireframe — because the region rules, which sit closer to the coordinates
      it was writing, ended with "leave those props out of image_regions and let the
      placeholder rule above fill them". A model that believes a prop is taken care of
      has no reason to describe it.

      So that clause now has two versions and the build picks by whether anything will
      draw the picture: point at the placeholder when nothing will, and at
      image_prompts when something will, naming the consequence of saying nothing. The
      ask itself is stated as a requirement rather than as an offer for the same
      reason.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> cc06d7

    • fix(image): recognise OpenAI's key and rate-limit errors by their wording (#93)

      A live run against the real endpoint with a deliberately bad key came back as
      "OpenAI image error: Incorrect API key provided: sk-…", not as the intended
      "invalid image API key. Check configuration." The SDK raises its own exception
      carrying the API's message body and nothing else, so a check for '401' never
      matches — the one failure an admin can act on was reported as a generic error.

      Match the wording as well as the status, and the same for the rate limit.

      Model\Provider\OpenAi::handleException() has the identical blind spot for chat
      calls. Left alone here: it is not this issue's code, and the fix belongs with a
      run that observes it the same way this one was observed.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> be718d

    • fix(content-builder): a free image rate is not an unknown one (#93)

      The page total read "cost is not known" off the numeric total rather than off
      whether a rate was found, so a store on a zero per-image rate — an internal
      proxy, a plan with images included, the override set to 0, all of which
      Helper\Config deliberately accepts — was told its pictures cost an unknown
      amount instead of nothing. Gate the wording on costKnown, which is the thing
      that actually tracks it.

      While there: an amount under a cent is written with four places rather than two
      in both the build note and the pre-build estimate. Two writes $0.0040 as $0.00,
      which in this line reads as "the picture was free" — the same claim Usage\Cost
      keeps its own precision to avoid.

      Reported by Copilot on PR #100.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 334c50

    • feat(admin): say what a build may spend on images before it starts (#93)

      A ceiling, not a forecast, and it cannot be otherwise: how many pictures a page
      needs is only known once the build call has answered, since the descriptions
      ride back on it. So the modal and the editor's chat panel show the most the run
      can cost — the cap times the rate — which is the number the cap exists to make
      true. Priced through the same ImagePrice the ledger writes, so the estimate and
      the invoice cannot disagree.

      One sentence, composed once and shared by both controls, which compose their own
      config JSON and would otherwise drift apart.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> c676d0

    • feat(content-builder): draw the picture a wireframe left a box for (#93)

      The other half of issue #85. Extraction answers a screenshot of a real design
      and answers nothing at all for a wireframe, where the region genuinely is a grey
      box and the merchant replaces the placeholder by hand.

      Second, not first, and the order is the point: extraction is free and exact,
      while one generated image costs $0.01 to $0.25 against about $0.03 for the whole
      text build that placed it. So generation runs only where extraction has already
      declined, and only where a prop passes every gate — the setting is on, the prop
      is a band's main image rather than an icon, the build call itself described a
      missing picture there, and WireframeDetector agrees the reference is a stand-in.
      Off by default, with a hard per-build cap that is a spend limit rather than a
      tidiness one, hence no "unlimited" at zero.

      The descriptions ride back on the build call like the regions do, so this costs
      no request of its own. An image model is configured on its own — Claude
      generates no images, so the text model says nothing about who can draw one — and
      lives in its own pool rather than as a row that could become the default a chat
      call routes to.

      Nothing here can cost the build: a refusal, a timeout, a missing key, a full
      disk or the cap each leave the dummyimage.com placeholder in place and say so in
      the build note, one note per prop rather than two contradicting each other.
      Every call that answered is written to the usage ledger as kind=image, priced
      through the same table the admin's pre-build estimate is priced through, so a
      page's cost is complete exactly where it is largest.

      The crop is deliberately not sent as a reference image. Under these gates it is
      the wireframe's own grey box: nothing to imitate, and billed as input. Its shape
      is used instead, to pick the size.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 83f19f

    • feat(image): tell a wireframe stand-in from a flat design (#93)

      PlaceholderDetector cannot be the trigger for generating a picture, and the
      reason is what its answer costs. There, a false positive keeps the
      dummyimage.com URL the build already used; in front of generation, a false
      positive paints an invention over a band a designer meant to be flat — a
      brand-coloured hero, a dark call-to-action strip — and bills for it. So the
      question has to be a different one, asked of positive evidence: not "is this
      crop empty" but "is this a wireframe at all".

      Answered of the whole screenshot, once per build, because a grey box in a mock
      and a grey box in a design are indistinguishable at the size of one crop. Two
      signals have to agree: chroma, which a design's photography or brand colour
      pushes up, and luminance entropy, which is what stops a black-and-white
      photographic design being read as a mock. A crop's own drawn marks — a cross,
      an outlined frame — are the second way in, for the design that is finished
      apart from the one band still holding a box.

      Measured against real files: this module's five-band mock lands at chroma 0.014
      and entropy 1.9, a storefront screenshot with photography at chroma 0.32, a
      photograph at entropy 5.1.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> ac3cba

  • 1.5.0
    • chore(release): 1.5.0

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> e0b3b7

    • Merge pull request #97 from breezefront/fix/96-field-actions-layout

      fix(admin): keep AI actions off the field's scope row (#96) 49631b

    • fix(uninstall): honour delete()'s bool channel as a failure (#96)

      WriteInterface::delete() reports failure two ways: the stock Write throws, but
      the interface declares a bool and a remote-storage implementation is free to
      answer plainly false. Ignoring the return let a false slip through and the
      uninstall carry on into dropTable(), leaving the crops on disk with the schema
      already gone — the exact half-removed state removing media first was meant to
      rule out. Treat both channels as the same failure.

      Not reachable on a stock install, where Write::delete() only ever returns true
      or throws. It is reachable through any other WriteInterface, and the guarantee
      is worth only as much as its weakest branch. 47f66b

    • fix(uninstall): take the generated crops too, and narrow the JS claim (#96)

      Second review round, both points real.

      --remove-data left pub/media/breezeai behind. MediaStorage owns that directory
      outright, and Prune — the job that collects crops no draft points at — leaves
      with the module, so anything kept behind would sit there uncollected forever
      under a command that claimed a full purge. Delete it, before the schema rather
      than after: an unwritable media directory is the likeliest failure here, and
      failing first leaves the install intact and retriable instead of tableless with
      its images still on disk. A failure is reported, not swallowed — the files are
      the one thing an uninstall cannot recreate.

      Saying so also means saying what it costs: pages built from a screenshot
      reference those crops and outlive the module, so the doc now spells out that
      --remove-data breaks their images, and that omitting the flag skips this class
      entirely for anyone who wants them kept.

      The doc also claimed no module JavaScript loads while the module is disabled.
      requirejs-config.js registers bcb-chat-mixin against the Content Builder panel
      unconditionally, so the mixin and its dependencies are still fetched there; they
      read an empty config and return without injecting anything. The guarantee is
      about injection, not loading, and it now says that. 1c073c

    • fix(uninstall): escape the LIKE prefix, and stop overpromising (#96)

      Four points from review, all of them real.

      `_` is a single-character wildcard in LIKE, so `swissup_breezeai/%` also matched
      paths like `swissupXbreezeai/...` — an uninstall could have taken another
      module's configuration with it. Escape the metacharacters and declare the escape
      character in the statement, using `!` rather than a backslash so the result does
      not depend on sql_mode=NO_BACKSLASH_ESCAPES.

      The E2E spec constructed admin URLs without the per-route secret key. Links on
      this stand do carry one, and an instance that validates it would have timed the
      spec out instead of testing anything. Read the URL out of the DOM, the way
      bulk-action.spec.js and page-builder.spec.js already do.

      Two claims in the removal doc were wrong. The Enabled flag suppresses what the
      module renders into someone else's form; it does not hide the module's own menu,
      which menu.xml declares unconditionally and gates by ACL. And removing the
      package cannot on its own fix a preference declared elsewhere: the compiler
      checks class_exists() before it checks whether the class was scanned, so taking
      the code out only swaps "has not been included in dependency injection
      compilation" for "does not exist". The declaring source has to go first. 3f1bed

    • fix(admin): keep AI actions off the field's scope row (#96)

      .admin__field-control holds more than the input. Magento renders the error
      label, the note, additional info and — at store-view scope only — the
      admin__field-service block carrying "Use Default Value" into it as siblings of
      the field. Making that container a flex row for the AI actions (#82) hoisted all
      of them onto the field's line; the field, at flex-basis 0, then collapsed to a
      sliver and its value read as empty. A merchant on 2.4.9 reported a store-scoped
      Text Area attribute rendering blank with the scope checkbox displaced, and
      rolled back to 1.2.0.

      Give every child its own full-width row, then opt the field and the actions back
      onto a shared first row. That keeps what #82 asked for and puts everything else
      back where it sits with no actions at all.

      Also ship the removal path the same report asked for: Setup\Uninstall drops the
      module's tables and configuration so module:uninstall --remove-data leaves
      nothing behind, and docs/UNINSTALL.md covers both turning the module off and
      taking it out, including why a disabled module's own di.xml cannot be the source
      of a preference the 2.4.9 compiler rejects. 9c5b39

    • feat(content-builder): let the AI place Magento widgets (#91) (#95)

      * feat(content-builder): let the AI place Magento widgets (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * fix(content-builder): describe only the enabled widgets, and offer no select we cannot list (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      * fix(content-builder): write the widget defaults the prompt promises, and report what a directive could not carry (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

      ---------

      Co-authored-by: Claude Opus 5 <noreply@anthropic.com> dd87e3

    • fix(content-builder): write the widget defaults the prompt promises, and report what a directive could not carry (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> d652df

    • fix(content-builder): describe only the enabled widgets, and offer no select we cannot list (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 60f747

    • feat(content-builder): let the AI place Magento widgets (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 5be597

    • Merge pull request #94 from breezefront/fix/vision-test-post-max-size

      test(vision): let a test narrow the post_max_size setUp established ee92e8

    • fix(content-builder): describe only the enabled widgets, and offer no select we cannot list (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> bbfe20

    • test(vision): let a test narrow the post_max_size setUp established

      The first willReturn matcher answered every invocation, so the second one
      a test body added never fired and the cap test asserted against 64M.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> a5fccd

    • feat(content-builder): let the AI place Magento widgets (#91)

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 3a19b3

    • Merge pull request #92 from breezefront/feat/85-image-extraction

      feat(content-builder): take a generated page's images from the screenshot (#85) 8b2d79

    • fix(image): scan a trimmed edge exactly, and compare whole origins (#85)

      Round four. Four of the five inline comments repeat findings already fixed in
      the two commits before this one; these are what was left.

      The trim sampled every Nth pixel along an edge, which is safe for a
      photograph's flat margin and wrong for the one case the trim exists to serve: a
      line icon's stroke is a pixel or two wide, can fall between samples, and the
      edge then reads as empty and the outline is cut off the icon. A crop small
      enough to be an icon is now scanned pixel by pixel; the sampled path stays for
      anything larger.

      The media base URL was compared to the web base URL by host alone, so media on
      https://shop.test:8443/ looked local to a storefront on the default port and
      was written as a root-relative path that resolves against the wrong server.
      Scheme, host and port are compared together.

      Prune read every matching content document into memory before picking the file
      names out of them. It streams the rows instead — the names are forty
      characters each, the documents are whole pages.

      Both descriptions of the setting said that turning it off makes every image a
      placeholder. Since the brief's own images are now left alone, that is no longer
      what happens.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 47ab31

    • fix(content-builder): keep repaired icons in their band, and check GD first (#85)

      Round three of the review.

      Clamping a box to its band and then squaring it up put it back outside: an
      icon against a section edge grew through the boundary and cropped pixels from
      the section next door. It is moved back inside rather than cut down, because
      cutting it down restores exactly the flattened box the repair exists to
      rescue. A box the grid flattened onto a single line is also kept now when that
      line falls inside the band — intersecting a zero-height box with anything
      leaves nothing, so the band check was throwing away the very shape squaredUp()
      was written for.

      WebP is an optional part of GD and every crop ends in an imagewebp() call, so
      a server built without it failed on the last step of each crop and kept every
      placeholder without saying why. The setting answers false there, once, with
      the reason in the log — and the prompt then does not spend tokens asking for
      coordinates nothing can use.

      The base screenshot rule lost the word "logo" when it was rescoped, which left
      an extraction-disabled build without the instruction it had before this branch
      existed. Restored.

      Prune's per-run cap now counts what it removes rather than what it looks at.
      Skipping a file costs a stat and an array lookup since the reference lookup
      became one scan per table, so spending the budget on files that were never
      going away only let them hide the collectable ones behind them, in the same
      order, every night.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> f0884f

    • fix(content-builder): keep the brief's images, and judge crops by the prop (#85)

      Four from the second review round.

      The stand-in host was matched with str_ends_with, so notdummyimage.com — a
      domain belonging to somebody else — counted as ours and an icon supplied from
      it would have had its switch closed. Matched as the host itself or a subdomain
      of it now.

      A crop's kind was decided by its size alone. The symbol thresholds are close to
      "anything but a blank square", which is what a monochrome line icon needs, and
      a wireframe's grey box with a cross through it is small enough to be handed
      them — so the one thing the detector exists to reject sailed past it. Size
      still decides how a region is cut; what the result is allowed to be is decided
      by the prop, and only a prop named for an icon is judged as a symbol.

      A background image the brief had already supplied was overwritten by the band
      fallback whenever the model reported no region for it. Naming an image is a
      decision and a region is a guess about where one is, so extraction now fills
      only a prop that is empty or still holds the generated stand-in — every image
      prop, not only the background that exposed it.

      Prune asked "is this file referenced" once per file: three LIKE queries against
      unindexed text columns, up to fifteen hundred full scans in one cron run on a
      backlog. It reads the names back out of the content instead, once per table per
      run, and not at all on a night with nothing old enough to remove.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 933f93

    • fix(content-builder): choose the screenshot, and the switch, deliberately (#85)

      Two more from the review, both about a decision that was being made by
      accident.

      BuildPage hands over every image the conversation carries, and extraction cut
      from the first of them. In the screenshot modal there is only ever one, but in
      the editor's chat panel the reference the admin has just sent sits behind the
      one they sent an hour ago — so the model described the new design and the crops
      came out of the old one, silently. A region names no image and nothing here can
      tell them apart, so the newest is cropped as the best available guess, and the
      build says so when there was more than one to choose from.

      The other is the icon case. Filling an image prop with a dummyimage.com box is
      right where the prop always renders: the merchant sees a labelled grey
      rectangle and knows to replace it. Behind a switch it is not, because the
      component offers a better answer — a feature card without an icon, which is
      what the switch's own default says. The stand-in now counts as unfilled there,
      and the host it is recognised by is the constant the prompt is written from
      rather than a second copy of the string.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 4c31e2

    • fix(content-builder): answer the review on extracted images (#85)

      Six things the review found, none of which change what a good run produces:

      - A background whose box was unusable fell back to its band and got its
      picture, but the failed box had already added a warning telling the merchant
      to set the image in the editor. The fallback is resolved first, and the
      warning is left for the case where nothing was found.
      - The symbol threshold was two colours, which is what a crisp monochrome icon
      quantises to. Its own docblock says "no second colour worth the name" — one.
      The WebP round trip usually adds enough noise to hide this, so it cost an
      icon only where the screenshot drew one cleanly.
      - Reusing a stored crop kept the old mtime, so a draft could adopt a file
      already past the retention window and have it pruned before the page was
      saved. A reused crop is touched.
      - Prune spent its per-run budget on files it had already decided to keep,
      which let a directory of recent crops hide the old ones behind them on every
      run. Only files past the cutoff count against it.
      - The upload limit bounds compressed bytes, not the bitmap they unpack into.
      The measurement already happens before anything decodes, so an implausible
      pixel area is refused there rather than in the allocation after it.
      - The README promised a warning for every unfilled image prop. A prop the
      design said nothing about passes silently, and that is the normal wireframe
      case, so the sentence now says what the code does.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 6e71f8

    • test(image): read the WebP signature instead of silencing getimagesize (#85)

      The Magento2 standard rejects the error suppression, and the assertion did
      not need it: the question is what bytes were written, which the RIFF/WEBP
      container signature answers on its own.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> c02438

    • feat(content-builder): take a generated page's images from the screenshot (#85)

      A page built from a real design came back with a dummyimage.com box wherever
      the design had a photo, and the admin replaced every one by hand. The merchant
      already handed us the picture: the model is now asked, on the build call that
      was happening anyway, where each image is, and the region is cropped out of the
      screenshot locally and stored in media.

      Two coordinate sources, because neither works alone. A per-prop box is the only
      thing that can locate an icon and is loose about it; a band's vertical extent is
      coarse but dependable. So a box is held to its own band before it is used — a
      hero box spanning three bands was the common failure on a tall screenshot — a
      box the 0..1000 grid flattened is squared up on its surviving axis, a small box
      is padded and trimmed back onto its own content, and a background image falls
      back to the band strip when no usable box came back.

      A crop that turns out to hold a wireframe placeholder is skipped and the
      dummyimage URL kept: a grey rectangle stored as the page's hero is worse than
      the placeholder it replaced. Symbols are judged by their own thresholds, since a
      line icon is monochrome by design. Generating an image for those regions is the
      separate second half of #85.

      Model/Image carries no Content Builder dependency — the per-band build loop of
      #84 crops the same screenshot with the same services. 53eece

breezefront / breeze-blank

14 hours ago success

breezefront / theme-frontend-breeze-enterprise-apollo

14 hours ago success
  • 3.3.1
    • Version 3.3.1 c08c13

    • Improve prices styles when both ex/inc tax are shown 7baf02

  • 3.3.0
    • Version 3.3.0 7f1f00

    • Added Contact Us page installer a791e7

    • Improve switcher label alignment inside mobile slideout a6415d

    • Fixed transparent menu icon for few seconds on slow web connection 7b8ab8

    • Sync gallery slider arrows with theme settings 6ce6f4

    • USP block content updated 96047c

    • Updated footer_top_content block content 946d00

    • Updated BCB homepage: moved to json; updated benefits block content 62bfe1

    • Fixed listing styles on Magento < 2.4.8
      LESS ^3.2.0 bugfix: This css block moved to the start of the styles. a38c1c

    • Firefox: Fixed horizontal scrollbar inside search slideout 613e59

breezefront / theme-frontend-breeze-enterprise-blank

14 hours ago success

breezefront / theme-frontend-breeze-blank

14 hours ago success

breezefront / module-breeze-content-builder

18 hours ago success
  • head
    • Declare the modules BCB actually needs a4923d

    • Fixed composer.json 975c9b

    • Added magento/module-ui dependency

      Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> 154d8a

    • fix(composer): declare the modules BCB actually needs (breezefront/breeze-content-builder#1)

      The metapackage does not need `swissup/module-core` — it arrives
      transitively through this module, exactly as in breezefront/breeze-ai#1.
      What the metapackage cannot fix is a module that under-declares its own
      dependencies, which is what breaks an install on a store that does not
      happen to ship every Magento module. Seven of the modules whose classes
      this one injects or instantiates were missing from `require`:

      - magento/module-catalog — `Block/Adminhtml/Product/Widget/Chooser`
      extends `Magento\Catalog\Block\Adminhtml\Product\Widget\Chooser`, and
      `FeaturedProductRenderer` injects `ProductRepositoryInterface`,
      `Helper\Image` and `Helper\Output`.
      - magento/module-widget — `Widget\Helper\Conditions`
      (`ProductGridRenderer`), `Widget\Model\Widget` and
      `Widget\Model\Widget\Config` (`AdminToolbarPlugin`).
      - magento/module-swatches — `FeaturedProductRenderer` promotes
      `Swatches\ViewModel\Product\Renderer\Configurable` as a constructor
      property, so DI compilation needs it present.
      - magento/module-catalog-inventory — `FallbackProductProvider` injects
      `CatalogInventory\Helper\Stock`.
      - magento/module-variable — `AdminToolbarPlugin` injects
      `Variable\Model\Variable\Config`.
      - magento/module-customer — `BcbContentRenderer` reads
      `Customer\Model\Context::CONTEXT_GROUP` for its cache key.
      - magento/module-configurable-product — `FeaturedProductRenderer` reads
      `Configurable::TYPE_CODE` with no guard.
      - magento/module-newsletter — `NewsletterRenderer` creates
      `Newsletter\Block\Subscribe` with no guard; nothing catches the failure.
      - magento/module-theme — already sequenced in `etc/module.xml`; it was
      the only entry there absent from `require`.

      Also tightened:

      - `php: "^8.1"` added. Promoted `readonly` properties are used throughout
      (`BcbContentRenderer`, every controller, the renderers), so 8.1 is the
      real floor. Matches `swissup/module-breeze` and
      `swissup/module-breeze-theme-editor`.
      - `magento/framework: "*"` → `"^103.0"`. `"*"` guarded nothing; 103.0 is
      the 2.4 line, and it is what `swissup/module-breeze-theme-editor` —
      already required here — asks for.

      Left as is, on purpose:

      - `swissup/module-core: "^1.13.1"` — already the tightest constraint in
      the family (`module-breeze` and `module-breeze-theme-editor` ask for
      `^1.12.27`) and 1.13.1 exists, so it resolves. Not widened.
      - `magento/module-review` and `swissup/module-marketplace` are soft:
      `FeaturedProductRenderer` guards the review block with `class_exists()`
      and `Installer/Command/BcbCmsPage` only names
      `Swissup\Marketplace\Installer\Request` in a docblock. Moved to
      `suggest` rather than `require`.
      - `swissup/module-breeze` stays out. The only coupling is
      `view/frontend/layout/breeze_default.xml`, a handle Magento loads only
      when Breeze is installed; `cms_page_view.xml` carries the rendering on
      any theme.
      - `magento/module-page-builder` and `magento/module-ui` appear in
      comments only.
      - The remaining `magento/module-*: "*"` constraints are untouched — no
      version floor is known to be wrong, and inventing one would be a
      narrower claim than the code supports.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 2dca6d

    • Merge pull request #36 from breezefront/fix/widget-description-for-ai

      docs(components): stop telling the AI a known widget directive is invented 45a7e6

    • docs(components): stop telling the AI a known widget directive is invented

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 3d1aa4

  • 1.2.0
    • Version 1.2.0 7f774f

    • Changes for support of the contact us page 812853

    • Added h1 for the Text component and switched to tags instead of CSS classes e054e6

    • Added new Map component c2d71b

    • Improve Columns vertical stretch 6b5da8

swissup / module-marketplace

20 hours ago success
  • head
    • Cleanup CSS ea255a

    • Fix grid styles 4d48e9

    • Stop running composer from the backend (#17)

      Running composer through the web server is not reliable, so the backend no
      longer dispatches composer operations. Install, Update, Remove, Enable and
      Disable now open a modal with the command to copy and run in a terminal, both
      for a single row and for a massaction. Run Installer stays a real backend
      operation - the one-click installer does not use composer.

      Enable and Disable had no console equivalent, so marketplace:package:enable and
      marketplace:package:disable were added (aliases marketplace:enable and
      marketplace:disable).

      Channel configuration and Tasks History are removed from the backend as well.
      Channels are managed with the marketplace:channel:* and marketplace:auth:*
      commands. With the settings form gone, ChannelsSave was the last job producer,
      so the whole queue is removed: JobDispatcher, QueueDispatcher, Validator, the
      Job entity, the activity widget, the queue crons and the job table.

      The SettingsDataProvider modifiers are kept as empty stubs so that the channel
      modules registering them in the pool keep compiling.

      BREAKING: the swissup_marketplace_job table is dropped on setup:upgrade, and
      HandlerInterface::validateBeforeDispatch() is removed - it had no callers left.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> cccd99

    • Ignore the packages with an invalid name

      The channel metadata is not validated, and the package name ends up in
      the command we suggest to copy and run. A name containing ;, $() or a
      whitespace turns that command into something else.

      Filtered where the channel data is read, so that such a package never
      reaches the grid, the suggested command, or the installer request. The
      pattern is the one composer validates the names with, so nothing that
      composer is able to install is dropped.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> 956e42

    • Improve package disable/enable operations cc8491

    • Address review comments

      - Massaction: require the row to expose the action before offering a
      command. Local.php marks every downloaded package as enabled and only
      overrides it for the modules, so a downloaded theme passed the shared
      disable check even though Links.php never adds Enable/Disable to a
      non-module row - marketplace:disable would then write a derived, bogus
      module name to config.php.
      - Copy button: writeText() is asynchronous and rejects when the clipboard
      is blocked. Copy now returns a deferred, falls back to execCommand on
      rejection, and the Copied label is shown only once a copy succeeded.
      - README grammar.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> f2fdaf

    • Stop running composer from the backend

      Running composer through the web server was never reliable, so the backend no
      longer dispatches composer operations. Install, Update, Remove, Enable and
      Disable now open a modal with the command to copy and run in a terminal, both
      for a single row and for a massaction. Run Installer stays a real backend
      operation - the one-click installer does not use composer.

      Enable and Disable had no console equivalent, so marketplace:package:enable and
      marketplace:package:disable were added (aliases marketplace:enable and
      marketplace:disable).

      Channel configuration and Tasks History are removed from the backend as well.
      Channels are managed with the marketplace:channel:* and marketplace:auth:*
      commands. With the settings form gone, ChannelsSave was the last job producer,
      so the whole queue is removed: JobDispatcher, QueueDispatcher, Validator, the
      Job entity, the activity widget, the queue crons and the job table.

      The SettingsDataProvider modifiers are kept as empty stubs so that the channel
      modules registering them in the pool keep compiling.

      BREAKING: the swissup_marketplace_job table is dropped on setup:upgrade, and
      HandlerInterface::validateBeforeDispatch() is removed - it had no callers left.

      Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> d70a96

    • Forward command output strings to terminal c17318

    • Allow using dry-run option 2d329d

    • Reuse composer_cache from user's directory if possible 9cc10a

    • Command shortcuts 2cfa4c

  • 1.11.0
    • Version 1.11.0 e5e9b8

    • Fixed PHP stan return type errors 49ac60

    • Allow to run installer for themes missing in composer.lock 7bb9ca

swissup / module-seo-pager

1 day ago success