Day 5 — Artifacts, Images, and Tests
Today Brandforge becomes a product. A successful run produces a visible preview, a provider-ready image prompt, and a report that identifies its inputs. Then tests drive the real executable through success and failure.
Compile rather than improvise
Section titled “Compile rather than improvise”compile_image_prompt accepts a validated BusinessProfile. It never receives the raw model response:
pub fn compile_image_prompt(profile: &BusinessProfile) -> String { format!( "Create one calm, minimal advertisement for {}.\n\ Approved factual claims:\n{}\n\ Use only approved claims. Do not invent metrics, awards, prices, \ addresses, phone numbers, or testimonials.\n\ Leave a logo-safe area; composite the real logo later.", profile.name, approved_claims(profile), )}The real implementation also includes services, service area, and palette. Prompt construction is now a pure function: same profile, same prompt, easy snapshot test.
Produce a visible offline artifact
Section titled “Produce a visible offline artifact”The required path writes ad-preview.svg. SVG keeps the first project dependency-light while making
layout, copy, palette, XML escaping, and logo-safe composition visible. Open it in a browser.
The optional live extension sends image-prompt.txt to an image-generation API and decodes returned
base64 into Vec<u8> before writing ad.png. Keep this adapter outside the renderer. A network model
may generate pixels; it may not bypass the claim audit.
For one-shot generation, OpenAI’s current image guide recommends the Image API; conversational editing uses the Responses API image tool. Read the linked guide before implementing the optional adapter because models and response fields are versioned external contracts.
Bind the run to its inputs
Section titled “Bind the run to its inputs”pub struct BuildReport { pub business: String, pub source_sha256: String, pub profile_sha256: String, pub supported_claims: usize, pub unsupported_claims: usize, pub artifacts: Vec<String>,}A digest is not proof that the input is trustworthy. It is an identity: if any byte changes, the run report changes. Store acquisition time and origin when you add live scraping.
Test the real product
Section titled “Test the real product”Unit tests cover validation and rendering. The integration test launches the same binary a learner uses:
let result = Command::new(env!("CARGO_BIN_EXE_brandforge")) .args(["build", "--source", source, "--profile", profile, "--output", output]) .output()?;
assert!(result.status.success());assert!(output.join("ad-preview.svg").is_file());assert!(output.join("run-report.json").is_file());The failure test asserts three things together:
- exit status is nonzero;
- audit evidence exists;
- publishable preview does not exist.
That is an executable product requirement, not merely a function test.
Run the completion gate
Section titled “Run the completion gate”cargo fmt --all -- --checkcargo test -p brandforgecargo run -p brandforge -- build \ --source fixtures/brandforge/site.md \ --profile fixtures/brandforge/business-profile.json \ --output target/brandforgeOpen target/brandforge/ad-preview.svg, then inspect every other artifact. You should be able to explain
which stage created it and which earlier validation it depends on.
Ship one extension
Section titled “Ship one extension”Choose one:
- add
--format jsonfor machine-readable CLI errors; - add a
HumanReviewclaim status; - add a real-logo path and composite it into the SVG;
- add an optional live image adapter with a strict timeout;
- add a golden test for
image-prompt.txt; - record the provider/model/prompt release in
run-report.json.
What you built
Section titled “What you built”You shipped a real Rust + AI product slice. It turns model-produced data into a visible campaign only after typed validation and evidence grounding. You used ownership, Serde, enums, traits, iterators, files, hashes, bytes, custom errors, pure functions, and end-to-end tests because the product demanded them.
Official provider reference: OpenAI image generation guide.
Finish with the Project 1 Revision →.