Portability

Requirements that keep brand assets useful across platforms and teams.

Documentation for BrandBuilder 3.0.1. Official release and exact skill asset.

Build the same kit from the same source on Claude, Codex, and a bare checkout. Probe local capabilities first and record explicit skips for optional renderers.

For asset handoff, use the Asset Language terms and logos/asset-aliases.json: preferred descriptive names and approved original paths deliver identical bytes. Keep the original paths when migrating consumers that pin direct asset URLs.

The capability model

Do not assume. Probe once, at the start, and record what you found:

python3 templates/probe.py

It prints a capability block and writes <kit>/qc/probe.json. Everything downstream routes off that. A missing tool gets named in VERIFY.md as a skip with a reason; it never gets silently substituted, and it never gets quietly skipped.

Three capability tiers, and what each can still finish:

TierWhat is presentWhat you get
CorePython 3.8+, coloraide, jsonschema, and the standard librarybrand.json, all tokens, the Next.js binding, enforcement, the guidelines page, the specimen, the manifest, verify.py and the full glyph gate
RasterCore, plus a rasteriser and Pillow for required compositingEverything above, plus PNG exports and the favicon set; a measured ICO writer adds the multi-entry .ico
FullRaster, plus headless ChromiumEverything above, plus the brand guide PDF and the QC contact sheets

The Core tier must always succeed. If a step cannot run at Core, it is written wrong. That is why validate_glyph.py carries its own rasteriser and why no gate depends on an agent being able to view an image.

Authoritative PNG logos follow the same rule. Core accepts only non-interlaced RGBA8 and compares exact binary topology using the owner-approved alpha or luminance mask tied to the current source hash. Bound passive SVGs are verified by exact embedded bytes; JPEG and WebP cannot bind a logo variant. Raster and Full independently rerender every logo PNG and compare platform PNGs plus ICO and ICNS frames with their declared verified masters, but they do not replace the Core authority verdict. Every generated derivative carries its source ID, source hash, variant, and transformations in logos/provenance.json, so capability handoffs cannot silently substitute another mark.

Vision is a bonus, never a gate

The house rule is still "look at every rendered artifact before shipping it", and an agent that can see images must still open the contact sheets. But no build is blocked on somebody having eyes, because on Codex nobody does.

Every quality question therefore has a measured form:

The questionThe measured answer
Is the mark correct?validate_glyph.py, all numbers, zero external tools
Does it survive a favicon?component and counter counts at 32 and 16 px
Is the guide usable?qc_render.py ink coverage, density, largest empty run, folio presence
Do elements split across pages?qc_paginate.py, DOM-level, exact
Is the contrast legal?coloraide at build time, never a typed number

When a rendered artifact cannot be produced at all, say so in VERIFY.md and in the handoff. "The PDF was skipped because Chromium is unavailable" is a fine outcome. "The PDF looks good" from an agent that never rendered it is not.

Python

  • Invoke as sys.executable from inside a script and as python3 from a shell, falling back to python when python3 is absent. On Windows, use python when python3 is unavailable.
  • Target 3.8. No structural pattern matching, no tomllib, no | unions in annotations.
  • Open every file with an explicit encoding="utf-8" and, on write, newline="\n". Windows defaults to cp1252 and CRLF, and both corrupt a checksummed manifest.
  • Install optional renderer dependencies with pip install --user; if installation fails, drop to a lower tier and record the skip. Missing coloraide or jsonschema blocks Core and must be fixed before building.
  • Core work requires coloraide for measured color and jsonschema==4.17.3 for registry validation. If either is missing, the probe blocks before writing a capability report. Font contract validation requires fontTools, and WOFF2 inspection also requires Brotli. Raster palette evidence requires Pillow. Report a missing required contract dependency explicitly; do not substitute or publish partial evidence.

Shell and paths

  • Build every path with os.path.join. Never interpolate / into a path.
  • Never depend on the working directory. Resolve relative to os.path.dirname(os.path.abspath(__file__)).
  • Do not pipe, glob or chain in subprocess. Pass an argument list.
  • Do not assume a POSIX utility exists. find, sed, md5sum and unzip are all absent somewhere.
  • Some sandboxes cannot delete files. Prefer overwrite-in-place to delete-then-write, and if a directory has to be replaced, write the new files over the old ones rather than removing the tree first.

External tools

Probe for every one of these and route to the first that answers:

JobFirst choiceThenThen
SVG to PNGrsvg-convertresvgthe bundled rsvg-convert.js on Node with @resvg/resvg-js
Multi-entry ICOmagickconvertPillow, with the per-size PNGs already rendered
PDFheadless Chromium via Playwrightnone: skip and record it
PDF inspectionpikepdfpdffontsskip

Two specific traps, both of which have cost a run:

ImageMagick 6 has no magick. It ships convert. A probe that tests only for magick reports the ICO step as a skip on every ImageMagick 6 host, and a skip reads as "not applicable" rather than "your favicon is broken".

Google Fonts is a trap, not a build tool. Fonts are bundled in the kit and ordinary generation stays offline. When an approved fixed face is absent, use the explicit controlled ingestion command with an authoritative HTTPS or controlled local source, expected hash, license evidence, contained destination, and atomic validation before the build begins.

Network

Assume there is none. Nothing in routine generation, verification, documentation, site preparation, or release packaging may require a network call. Controlled font ingestion is a separate operator-invoked preparation action and never runs implicitly.

Every generated kit also carries the exact pinned BrandBuilder distribution under enforcement/distributions/. Each distributed skill contains SOURCE_REVISION, which binds generated provenance to the BrandBuilder commit that produced the release without consulting the consumer repository. enforcement/consumer-contract.json records the distribution filename, compiler version, contained path, and SHA-256. A fresh consumer verifies and uses these delivered bytes before considering an authorized exact-version network recovery. It never installs an unspecified latest release.

Frontmatter and entry points

Different hosts read different things, so the skill ships both:

  • SKILL.md with frontmatter limited to name, description, license, compatibility, metadata and allowed-tools. Anything else, user-invocable in particular, hard-fails claude.ai and Skills-API upload validation.
  • AGENTS.md at the root, plain Markdown with no frontmatter at all, saying the same thing in the same order. This is what a Codex or an agent working from a bare checkout reads. It must stay in step with SKILL.md: when the routing table changes, both change.

The same contextual Author, Implementation, and Audit policy appears in both entry points because AGENTS.md is regenerated from SKILL.md. Consumer kits carry a separate concise governed block that points to their exact generated IMPLEMENTATION.md and consumer contract.

Write instructions as file paths and shell commands, not as tool names. "Read references/08-glyph-construction.md" works everywhere. "Use the Read tool on" works in one product.

The single most portable habit

Prefer a script that a human could run over an instruction a model has to follow. python3 templates/build_kit.py . behaves identically on every provider. A paragraph telling the agent what order to do six things in does not.

Every time a step turns out to be provider-dependent, the fix is to move it into a template and have the prose call the template.

Check the target host

After importing a generated icon, inspect the host's own packaging and display: Apple app icon guidance, Windows icon design, and maskable web icons describe different targets. A kit source file proves what was delivered, while a host preview proves how that exact file appears there. For interface behavior, preserve native controls and labels described by HTML semantics or the target platform's equivalent. This task does not require redrawing the approved master.

On this page