ADR-008: Consistency and likeness as switchable modes
Who is this for
Section titled “Who is this for”Developers and the owner — read this before tuning quality, and before deciding which mode an event runs in.
CONSISTENCY_MODE=1(default): one anchor portrait first, then all sheets in parallel referencing it. The 12 stickers match each other; the face can drift from the guest.LIKENESS_MODE=classic: the selfie and a face crop are the only face source; no anchor. Closer to the guest; colours can drift between sheets.LIKENESS_MODE=hybrid: classic, plus skin and hair colours pulled to the pack median by code.- Status: accepted as flags; the long-term default is an open decision — see Open decisions.
Context
Section titled “Context”Two quality complaints pull in opposite directions.
- The stickers differ from each other: hair length, hair colour, skin tone, stubble and even clothing drifted between sheets, because each sheet was an independent sample with only the selfie as reference.
- The stickers are pretty but not very like the guest: with an anchor as the main reference the face is a copy of a copy. The model first interprets the selfie into a portrait, then twelve stickers copy that portrait.
Neither could be settled by argument, only by live runs, and live runs cost money. The practical answer was to keep each scheme behind a flag so the mode can be changed on the server in a minute.
Decision
Section titled “Decision”| Mode | Face source | Sheets | Consistency mechanism | Checks |
|---|---|---|---|---|
Consistency (CONSISTENCY_MODE=1, LIKENESS_MODE empty) |
Anchor portrait (main) + selfie | In parallel | HARD LOCKS prompt block, skin normalisation to the anchor |
Anchor verified against the selfie; pack checked against the anchor |
Classic (LIKENESS_MODE=classic) |
Selfie + face crop | Sheet 1 first, the others reference it | Prompt locks only | Each sheet checked against the selfie; a failed figure is redrawn alone |
Hybrid (LIKENESS_MODE=hybrid) |
Selfie + face crop | As classic | COLOR LOCK in prompts; skin and hair pulled to the pack median in code; despill |
Pack checked against the selfie |
LIKENESS_MODEtakes precedence overCONSISTENCY_MODE.- Shared by all modes: sheet layout, cutting, edge rules, regeneration limits, cost accounting and the cost cap.
- Skin normalisation shifts the whole face region and is capped (
SKIN_NORM_MAX_DE), after patches appeared on very light skin. - Decisions about “passed or failed” are made in code from the vision model’s structured answer, not by the model.
Implementation:
bot/services/consistency.py,
likeness.py,
skin_tone.py,
appearance.py.
Alternatives considered
Section titled “Alternatives considered”| Alternative | Why not |
|---|---|
| A face-segmentation or face-embedding library | No wheels for the local Python version, heavy weights and dependency; colour targets are measured from the face box instead. |
| Pull colours to the selfie itself | Station lighting overexposes the photo; the pack would turn pale. Hybrid uses the pack median and lets the selfie nudge it by a small, capped amount. |
| One mode only | The trade-off between sameness and likeness is not resolved yet. |
Consequences
Section titled “Consequences”- Consistency raised the cost of a pack from about $0.25 to about $0.41 and, together with parallel sheets and faster cutting, lowered the time from about 99 s to about 60 s (COST_HISTORY.md, “Cost and time of a pack by stage”).
- Three code paths must be kept working; each has its own tests with mocked AI.
- The mode a production server runs in is a line in its
.env, not something the repository records. Check theSTARTUP likeness=…log line. - Classic and hybrid have been validated on few faces; a wider live comparison is still owed.
Evidence
Section titled “Evidence”HANDOFF.md: sections onCONSISTENCY_MODE,LIKENESS_MODE=classic,LIKENESS_MODE=hybrid, skin patches.- Commits
756f489,edbbf06,8d3b61b,ecb43e4,5dbf8ae.
Where to go next
Section titled “Where to go next”- Generation flow.
- Configuration — how to switch the mode on a server.
- Decisions index.
Last verified: 2026-11-13 against ai-sticker-pack@b715418 and ai-stickers-landing@e350ff5.