A gallery run took every view twice, once with the injected snippets
stripped. The comparison is only needed when the operator asks for it
for one role, so captureDesignGallery now captures the "after" side
alone and adds the plain side when PLAYWRIGHT_GALLERY_BEFORE is true.
make design-gallery passes it through as before=true; gallery.sh
refuses any other value, and rerun-spec.sh hands the variable into the
Playwright container. The deploy-driven run sets no such switch, so it
captures the designed side only.
The design loop page and the requirement describe the gallery as the
designed state and name before=true for a comparison.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The before/after gallery of a role had three gaps that cost a full
rerun or produced a wrong "before" screenshot without a failure:
- A view behind a redirect or a hash route kept the injected snippets
on its plain side, because neither passes page.route(). The helper
now loads such a document once more by the URL it ended on and fails
the view when the plain side still carries the snippets.
- A state that only exists with the injected snippets had no plain
side to capture. A view marked `afterOnly: true` skips it.
- Looking at one view meant a temporary test or the whole gallery.
`make design-gallery app=<role> views=a,b` runs the gallery test
alone, captures only the named views and adds them to the existing
screenshots.
The view names travel as PLAYWRIGHT_GALLERY_VIEWS into the Playwright
container. The name stays out of the INFINITO_ registry on purpose: it
is a call parameter, and a default in .env would silently narrow every
later gallery run.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
make design-palette renders a deployed app with another base color, runs
its design assertions and renders the base of the inventory again through
an EXIT trap, also when a render or an assertion fails. sync=design
re-renders the static design files, sync=role re-runs the app role for
values it bakes at deploy time.
make design-gallery takes pw= to replace the default pattern. Such a run
adds its screenshots to the existing ones, so a single view is recaptured
without a full run.
The role pass now runs the gate once after its last edit, checks the
palette with blue only, repeats the full deploy at its end only when it
changed provisioning and has a wall-clock budget per class. The
verification decision of the requirement records the same rule.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
The shared design helper gains tokenValue, assertToken and
assertLightAndDark. assertToken polls the computed property of an
element until it equals the value of a token. assertLightAndDark
demands that the surface behind an element is darker in dark mode than
in light mode.
assertReadable switches CSS transitions off, waits two frames and the
finite animations per mode, reads every color back from a canvas pixel,
so any CSS color syntax is measured, and blends a translucent text color
with its background. A selector that matches nothing visible fails
unless it is passed as { selector, optional: true }, and a call that
measured no element fails.
make design-gallery runs the design tests without retries, so a failing
test is reported after one attempt.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
make compose-role-sync runs only the role of one deployed application,
with its proxy vhost and injected snippets. It marks every shared
service of the stack as converged and skips the stack-wide service
stop. With pw= it stages the Playwright spec of the role again, renders
its env and runs it. make design-sync keeps re-rendering only the
shared CSS, the role stylesheet and the branding assets. Both run
through one playbook-sync.yml with a scope, which replaces
playbook-design.yml.
The host placement of the proxy and the shared services moves from the
constructor stage into tasks/utils/constructor/placement.yml, so the
role sync can include it.
base='<hex>' on both targets passes DESIGN_BASE_COLOR. The development
inventory references that variable for the design base color and keeps
#FFA500 as its default, so a deployed role can be rendered and checked
with another palette.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
web-svc-css becomes web-svc-design and owns the configuration that lived in group_vars/all/13_design.yml. Consumers switch their css service key to design, and sys-front-inj-css becomes sys-front-inj-design. javascript stays an independent key; a role's optional design.js.j2 is injected together with the design and CSP-hashed like the functional script.
An in-repo OKLCH lookup replaces colorscheme_generator. From design.colors.base alone it derives surfaces, text, borders, the primary and status fills with their on-colors, hover and active states and a dedicated dark palette; a unit test proves WCAG AA, and AAA for body text, across six base colors in both modes. Semantic --design-* tokens replace --color-NN-SS in every role stylesheet. The shared element styles sit in the cascade layer infinito-design, so an app's own design system always wins and takes the palette through a variable mapping in its role stylesheet or through its own theming mechanism.
design.logo and design.title resolve globally from web-svc-design or per role from its design entry, and false or 0 disables the replacement. The design_assets action renders the logo lockup per slot as SVG, PNG and ICO, and the legacy title keys move into the design entries.
Three roles carry the design end to end. The dashboard takes logo, favicon and title from the generator and replaces the hard-coded port-ui colors. Gitea maps its theme variables onto the tokens and mounts the generated logo and a branded start page. Nextcloud receives primary color, logo, name and slogan through occ theming and ships no stylesheet.
make design-sync re-renders the static design files of a deployed app, make design-gallery captures before and after screenshots in light, dark, desktop and mobile, and make design-queue orders the roles that are due for a design pass. The i8-designer skill and docs/agents/action/design.md describe that loop.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>