Prepared for the Product Designer role at Lendable

A design process you can check.

ux-factory is the tool I am building to take a product idea from its first question to an engineer-ready handoff. Every decision is kept with its evidence, and every screen draws on one token contract. The agents' runs are committed beside the work. This page shows how it works, what runs today, and one Lendable-shaped idea sketched for it.

Discovery question bank
76entries
Build-check groups in CI
51groups

Two problems, one system.

A static portfolio shows finished screens. It cannot show how the decisions behind them were made, so the reader takes the process on trust. ux-factory runs the process and commits the evidence: the questions asked, the answers given, the agent runs and the checks that passed. The second problem sits earlier. Design usually starts after someone has already decided what to build, and that discovery ends as prose nobody can audit. Here the decisions are recorded first, and the build reads them. So the project has two jobs. Today it is a portfolio you can verify. Its finished state is the tool for making the next real product.

Four stations, one brief.

Each station takes what the one before produced. For a product team at a lender the order matters. What to build, and for whom, is answered and written down before any screen exists, and every screen can point back to the decision that asked for it.

One brief, four stations: the finished state. Each station consumes what the one before it produced. Status chips are as of 3 October 2026.
  1. Decide

    Shipped
    In
    A product brief and the person who owns it.
    What happens
    A scripted, attributed question bank (76 entries, stages 1 to 9, a 12-question opening set and five facet modules) runs as a live agent session in the portal. The agent judges each answer against that question’s own weak-answer note. Every op is one tool call into an applier.
    Out
    A generated PRD: every decision names its evidence and its kill criterion.
    • Shipped Discovery partner, epic #279, closed 14 September 2026
    • In progress PRD fidelity: from complete-looking to buildable (epic #504)
  2. Build

    In progress
    In
    The PRD and its run package.
    What happens
    A free canvas: real components under the brand pack on real screens, states as base plus overrides, the flow as recorded connections. The agent composes only within the validated vocabulary and proposes the rest for the owner to ratify. A refusal is visible, never a silent fallback.
    Out
    Screens, their states and the flow between them.
    • Shipped Free canvas in place of the grid
    • Shipped Generic primitives: stack, text, list, icon, choice
    • Shipped Import from Brilliant and Figma
    • Shipped Compose loop, ratify, and a ledger of what the agent did, refused and corrected
    • In progress Run 1: Faster Payment built from its PRD (#316), then close-out

    Epic #295, open.

  3. Hand off

    Partly shipped
    In
    The built screens, states and flow.
    What happens
    A pack is generated, never edited by hand: ComponentSpec and DataContract from one source, token targets for CSS, iOS and Android, the agent vocabulary, Web Component wrappers and the Figma import path.
    Out
    An engineer-ready handoff pack.
    • Shipped The pack, with an llms.txt routing index
    • In progress Backend seam: bindings, one command contract, a conformance check (epic #329, six open slices)
  4. Show

    Shipped
    In
    The pack and the committed agent runs.
    What happens
    The public site replays committed runs: two data-connected prototypes with agentic slots (ask, propose, adjust), the component catalogue, traces and gates. A company brief compiles to a private, unlisted instance under that company’s derived pack.
    Out
    A public replay a reader can check step by step.
    • In progress Trace player marks what the agent said against what it did (#496)

The shared spine, under all four

  • Token contract. One DTCG source generates the CSS; a re-skin is one line in the head.
  • Gates. Build checks, generator drift, token lint, a pixel gate and CodeQL run in CI on every change.
  • Recorded traces. Agents run at build time and are replayed at view time, labelled “real run, curated”.

Discovery, written down as it happens.

A lending product carries calls about affordability, vulnerable customers and what happens when a payment fails. When those calls live only in a meeting, nobody can check them later. Decide asks them as questions, pushes back on thin answers and keeps the reason and the kill criterion beside each decision, so a designer can show why a screen exists.

The Decide station: a question bank, a live session that pushes back once on weak answers, a PRD projected from what was recorded, and a requirements hierarchy that ties each decision to the one it serves. Status as of 3 October 2026.
  1. Question bank

    Shipped

    76 entries over nine stages: 65 from the source research, plus 11 added (four non-functional, six on AI interaction, one on scope parked for later).

    Each entry names its source method, carries a provenance label (observed, derived or thin) and a weak-answer note: what a weak answer to it sounds like.

    Stages, with entries per stage

    1. Problem framing6
    2. Demand and evidence7
    3. Market, wedge and strategy6
    4. Solution shape and scoping12
    5. Business model, especially SaaS8
    6. Complex, regulated and workflow-heavy products8
    7. Measurement and kill criteria7
    8. AI-era questions18
    9. The famous killer questions, with provenance checked4

    A session asks a selection, never the whole bank: scope check 6, opening set 12, full discovery up to 31.

  2. Live agent session

    Shipped

    Runs in the local portal. The agent judges the form of each answer against that question's weak-answer note, never its substance. It may not say an answer is wrong.

    When an answer is weak it names what is missing and asks once more. The second answer closes the question. There is no third ask.

    Every op is one tool call into the applier

    • record_decision
    • flag_weak_answer
    • open_question
    • file_evidence

    A decision op has no field for answer text. It points at the person's answer by reference, and only the server writes answers, verbatim.

  3. Generated PRD

    Shipped

    Projected from the recorded ops by a pure fold: the same run always gives the same page, and a claim the ops do not carry cannot appear on it.

    • Every decision names its evidence, or is flagged no evidence on the page.
    • Every decision states its kill criterion, the field wrong_if. The applier refuses a decision without one.

    In progress Follow-on epic #504: grading 11 committed PRDs on 22 criteria found no decision log, acceptance criteria or sign-off line in any of them. Those sections are being added.

  4. Requirements hierarchy

    Shipped

    Each decision is filed at one level and names the decision above it that it serves. A decision with no parent is flagged orphan. The levels come from BABOK.

    1. Business What and why. No parent, by definition.
    2. Stakeholder What a person can do. Serves a business decision.
    3. Solution Functional and non-functional. Serves a stakeholder decision.
    4. Transition How the organisation gets from today to there. Serves a solution decision.
  5. Feeds the Build station

    In progress

    A screen composed on the canvas cites the decisions it answers, by their number in the ledger.

    Still open: building one real flow from its PRD on the canvas (#316), and links from each decision forward to its screens (#514).

One question, worked through: Rate path

Illustrative

Illustrative. Built from Lendable’s public site only; not Lendable work. The question and its weak-answer note are real bank entries. The answers, follow-up and decision are written for this page, not taken from a recorded run. Rate path is the idea in section 07: after a soft-search quote lands in the Fair or Limited band, show the total cost in pounds beside a better band, the factors that move a band, and an opt-in soft re-quote later, with “borrow now” kept as an equal choice.

Question

“What would this metric look like if we were gaming it, and what counter-metric would catch that?”

Stage 7 · derived, standard in the North Star literature as guardrails

Weak-answer note: no counter-metric. Every engagement metric has a degenerate maximum, usually notifications.

Weak answer

“We track how many people opt in to the later re-quote. If that goes up, Rate path is working.”

Agent’s follow-up

“The answer names one metric and no counter-metric. Opt-ins would also rise if the screen talked people out of borrowing now. What would you see if that were happening, and which number would catch it?”

Op: flag_weak_answer, missing: a counter-metric; what gaming the metric would look like.

Stronger answer

“Gaming it would look like opt-ins going up while people who opt in never come back for the re-quote. That would mean we delayed them rather than helped them. So the counter-metrics are two. Among Fair and Limited quotes, the share choosing borrow now should not drop against the screen without Rate path. And people who opt in should reach a re-quote and see their band hold or improve.”

Decision recorded
  • Level Solution, serving the stakeholder decision “an applicant quoted in the Fair or Limited band can compare borrowing now with waiting, in pounds, and choose either”
  • Evidence None filed yet, so the page flags this decision no evidence. Evidence the session would ask for: quote-to-offer-to-drawdown by band.
  • Wrong if (kill criterion) At the first read after launch, opt-ins have risen while borrow-now choices among Fair and Limited quotes have fallen, or most people who opted in never reached a re-quote.

One set of names for every surface.

The job description asks for a consistent visual language and for inconsistencies to be flagged. That gets harder as more screens come from more hands, some of them AI tools. Here every component reads the same semantic names, and the values behind them come from one source file, so web, iOS, Android and the Figma import path start from the same place.

1 · Three layers, loaded in order

  1. Layer 1

    The contract

    tokens.contract.css

    Every semantic token a component may use, each with a neutral fallback. It never carries a brand, so a page still renders with no pack loaded.

    Shipped

  2. Layer 2

    A brand pack

    tokens.neutral.css · tokens.verdant.css · tokens.saulera.css

    Primitives (the brand's own values) bound to the semantic names. Re-skinning a whole site is one <link> line in each page's head.

    Shipped

  3. Layer 3

    Token-only components

    components.css

    No literals: every colour, space and radius is a semantic token. Token lint in CI fails any token a component uses that the contract does not declare.

    Shipped

Same component, two token sets

The card markup and its CSS are identical in both. The only difference is which values the wrapper binds to the semantic names. This is the mechanism a brand pack uses, at the scale of one element.

This page's pack

Agreement

Monthly repayment

£214.60

Next due 14 November

Inverse set, six overrides

Agreement

Monthly repayment

£214.60

Next due 14 November

.scope--inverse {
  --color-bg-surface: var(--color-bg-inverse);
  --color-fg:         var(--color-fg-on-inverse);
  --color-fg-muted:   var(--color-fg-on-inverse-muted);
  --color-border:     var(--color-inverse-line);
  /* …two more, all token to token */
}

Illustrative card and figures, built for this page.

2 · One source, generated targets

Source of truth

DTCG token source

system/tokens.source.json

W3C Design Tokens format. A new token enters the contract group here first, with a neutral fallback; brand values bind in the pack.

Shipped

Generators

gen-token-css · gen-handoff · gen-vocabulary

agent-layer/*.mjs, with Style Dictionary for the platform builds

Drift-check gate

CI regenerates every output in memory and compares it with what is committed. Any difference fails the build, so nothing downstream is edited by hand.

Shipped

The handoff pack · never edited by hand

The pack is generated and committed today. Six slices that close its remaining gaps are open, so the pack as a whole is Partly shipped

  • CSS tokens

    tokens/css/contract.css · neutral.css

    Shipped

  • iOS and Android tokens

    FactoryTokens.swift · tokens.xml

    Generated today. Spec-matching token names, the contract group and type tokens for both platforms are an open slice.

    In progress

  • ComponentSpec

    pack.json, from system/specs/*.md

    Shipped

  • DataContract

    contracts/*.contract.json · JSON Schema

    Shipped

  • Agent vocabulary

    vocabulary.json

    The only parts an agent may compose with.

    Shipped

  • Web Component wrappers

    wc/vd-*.mjs

    Shadow DOM, styled only by the tokens the spec declares. Three data-bound components so far.

    Shipped

  • Routing index

    llms.txt

    One line per pack file: what it is, and when to read it. Generated and gated.

    Shipped

  • Shipped component CSS and data bindings

    components.css · bindings · one command contract

    So an engineer can wire a real service to the pack without asking design. Open slices.

    In progress

  • Figma import path

    figma-import.md · tokens.dtcg.json

    Four import routes documented. The parity run against a real Figma file has not landed yet.

    In progress

What this means for a design team: brand guidelines become machine-checkable, so an off-brand value or a drifted token is flagged by a gate rather than spotted by eye.

Agents propose. People decide.

The job description expects AI in daily work. In a lending product that raises a plain question: who decided this screen, and on what grounds? In ux-factory a person writes the brief and approves anything new. The agent proposes from a fixed vocabulary, and each run is committed so a reviewer can replay it and check.

127.0.0.1 portal, never deployed

Build time: the only place a live model runs

  1. Owner writes the brief

    The problem, never the answer. No board, no worked example.

    Shipped
  2. Agent proposes an op

    One of the eight verbs in the op vocabulary, nothing else.

    Shipped
  3. One tool call per op, into an applier

    The run is fenced: no file writes, the brief is the only read.

    Shipped
  4. Validator accepts or refuses

    A refusal is shown by name, never a silent fallback.

    Shipped
  5. Owner ratifies anything outside the vocabulary

    A proposal joins the vocabulary only on the owner's word; every gate runs and the diff comes back.

    Shipped
  6. Composition judge and evals

    Named rules checked against each committed composition. It reports raw counts and gives no score.

    Shipped
  7. Ledger records the run

    What the agent did, refused and corrected stays readable.

    Shipped
  8. Trace committed

    Raw and curated pair in the repo, beside the board it built.

    Shipped

Public site, the reader's browser

View time: no model call

  1. Vanilla HTML, CSS and ES modules

    No framework, no build step, no runtime dependency.

    Shipped
  2. Replay driver steps through the trace

    The committed ops play back at the run's real pacing.

    Shipped
  3. Labelled "Real run, curated for length"

    The label lives in the trace file itself, and the raw run sits beside it.

    Shipped
  4. Prototypes with agentic slots

    askproposeadjust

    Shipped
  5. Trace player marks said versus did

    Each replayed card shows whether the agent said it or did it.

    In progress
  • Verifiable

    Open the trace and check the run yourself.

  • Cheap and safe

    No live model at view time: no per-visit cost, no prompt for a reader to steer.

  • Honest

    A bad run is fixed by a tighter prompt and a re-run, never hand-edited.

Agents at build time, replayed at view time. Every step on the left produces a file that is committed; the public site only reads those files.

Checks that leave evidence.

Edge and error states are where a lending product can hurt someone: a missed payment, a failed affordability check, a payee name that does not match. A check that fails the build when a declared state is missing keeps those screens from being dropped late. Each check is code in the repo that a reviewer can open and run.

  1. Change

    A branch, often written by an agent.

  2. Authoring checks

    Journey drivers, morph checks, the composition judge. Run by the operator; they do not block a merge.

  3. Pull request

    Opened ready for review.

  4. CI gates

    Four jobs: verify, visual, codeql, audit.

  5. gates-green

    The one check branch protection on main requires.

  6. Merge

    Into main.

  7. Deploy

    A manual operator step; nothing deploys on merge.

Tokens and brand

  1. token-lint

    CI and authoring Shipped
    What it proves
    Every token the component stylesheet names is declared in the token contract, every contract token has a consumer, and the DTCG token source validates. Today: 63 contract tokens, 0 undeclared, 0 orphaned.

    For a designer: a component cannot ask for a colour, space or type step the brand contract does not define, and dead tokens do not pile up.

    What failure looks like
    The verify job stops and names the undeclared or orphaned token.
    What it cannot see
    A raw colour value typed straight into a stylesheet. It reads token names, not literal values.
  2. drift-check

    CI and authoring Shipped
    What it proves
    15 legs re-run the generators without writing and compare against what is committed: token CSS, the icon subset, the handoff pack and component vocabulary, replay files, each build package’s handoff.

    For a designer: the token files, icons and handoff pack a developer receives are exactly what the source produces. A hand-edited generated file fails.

    What failure looks like
    The leg and the drifted file are named, and the run exits.
    What it cannot see
    The per-company projection chain, which needs a jobs folder outside the repo.

Components and composition

  1. build-checks

    CI and authoring Shipped
    What it proves
    51 groups import the shipped modules with no browser: pattern rules, slots, compositions against the generated vocabulary of 26 components, the share link’s tamper refusals, the catalogue, the icon subset, the import chain, ratify. Every container’s declared children are rendered one level deeper, with a control that must go red.

    For a designer: every component in the vocabulary has a render path, and a broken composition rule fails by name instead of shipping an empty box.

    What failure looks like
    The group and case print red and the run exits; a container that drops a child is named as the parent and child pair.
    What it cannot see
    How anything looks or behaves in a browser. That belongs to the pixel gate and the journey drivers.

Journeys and pixels

  1. Pixel gate
    visual-regression

    CI Shipped
    What it proves
    11 shipped pages, each under two token packs, screenshotted and compared pixel by pixel against 22 committed baselines.

    For a designer: an unintended visual change to a shipped page fails the merge. An intended one must re-baseline in the same pull request, so it shows in review.

    What failure looks like
    The visual job goes red and uploads a diff report showing what moved.
    What it cannot see
    It never interacts, so a dead control compares clean. Up to 100 changed pixels pass. It captures without reduced motion. On feature/v3-* branches it reports but does not block, by design.
  2. Journey drivers (7)

    Authoring Shipped
    What it proves
    Seven drivers (build, canvas, catalog, instance, proto, ratify, studio) use real pages in Chromium, Firefox and WebKit: tamper refusals, an emptied board, an oversized file refused, reduced motion, the same command from pointer, keyboard and agent giving the same result.

    For a designer: the edge and error states in a flow are exercised in three browser engines, not only the happy path.

    What failure looks like
    The driver’s own last line reads “N assertion(s) failed”, with passed and failed counts per engine.
    What it cannot see
    They are not registered in CI, so a red driver does not block a merge.
  3. vt-verify

    Authoring Shipped
    What it proves
    View-transition morphs actually open, in each engine: none on page load, one per interaction family, none under reduced motion while the interaction still completes.

    For a designer: motion that silently stopped firing is caught, and reduced-motion users still reach the end state.

    What failure looks like
    A missing or extra transition group, named.
    What it cannot see
    Whether the motion looks right. It counts and names transitions; it does not judge the animation.
  4. vt-stack-audit

    Authoring In progress
    What it proves
    Before an element is named for a view transition: nothing moves when the names are removed, and nothing positioned overlaps a named element from outside it. That is the bug class that once hid a board’s connection lines at rest.

    For a designer: adding motion cannot quietly break the layout people see when nothing is moving.

    What failure looks like
    A hazard reported per page, naming the element.
    What it cannot see
    It false-positives on 3 of 7 shipped pages, so it is not yet an unattended gate.

Content and honesty

  1. Composition judge

    Authoring; CI proves it can fail Shipped
    What it proves
    A judge with no model in it runs 10 named rules over every committed composition, each one a rule the agent was already given: buttons are verbs (never “Submit” or “OK”), link text says where it goes, a critical row says why, an empty state offers a next step, sentence case throughout.

    For a designer: copy rules are checked on what the agent actually produced, and the judge is never fed back into the prompt.

    What failure looks like
    One line per failed rule. On 3 October 2026: one scenario 55 of 55, the other 53 of 55, with two sentence-case misses (“east warehouse”). The fix is a tighter prompt and a re-run, never a hand edit.
    What it cannot see
    It does not render, and it does not decide whether a composition answers the question. Taste stays with a person.
  2. Trace and replay legs

    CI and authoring Shipped
    What it proves
    Every committed agent trace passes the trace-format validator, and the replay files the site plays regenerate from those traces to exactly what is committed.

    For a reader: an agent run shown on the site is the recorded run, not a re-authored one.

    What failure looks like
    drift-check names the trace or replay file that disagrees.
    What it cannot see
    Whether the run was a good one. That is the judge’s read and a person’s.
  3. Group-count leg

    CI and authoring Shipped
    What it proves
    The build-checks pass line, the project rules file and the gate reference must all state the same number of groups.

    For a reader: the documentation cannot claim more coverage than the code runs.

    What failure looks like
    drift-check names the document whose count disagrees.
    What it cannot see
    Counts stated anywhere else in prose are not checked.

Security and merge

  1. codeql

    CI Shipped
    What it proves
    GitHub’s static analysis, read back in two passes: the pull request’s own diff, and the full tree on main. Any open high or critical alert fails. The 14 high alerts it first found were fixed in code, none dismissed.
    What failure looks like
    The job lists the blocking alerts and says whether this pull request or main carries them.
    What it cannot see
    Files outside its hand-kept path list. Origin checks and the honesty rules stay with build-checks and review.
  2. audit

    CI Shipped
    What it proves
    The difference in npm security advisories between the base and the change, across every lockfile. A new advisory fails.
    What failure looks like
    The new advisory is named.
    What it cannot see
    Advisories the base already carried, or ones published after the merge.
  3. gates-green

    CI, required check Shipped
    What it proves
    Green only when verify, visual, codeql and audit all succeeded, reading the pixel gate’s true outcome. A pull request cannot merge until it is green.

    For a designer: what reaches main has passed every CI gate above.

    What failure looks like
    The pull request cannot merge.
    What it cannot see
    The owner can still merge past red, deliberately. A pull request is not re-tested if main moves after it ran.

Not gated: the screen-reader pass and judgement-level accessibility (labels that say what they do, colour never the only signal) are checked by hand. No automated accessibility scanner is in the stack.

Planned, not yet a gate: a conformance check that tests a running service against the handoff pack’s contracts (contract-check, in progress).

Gates as evidence: every change to ux-factory passes named checks before it reaches main, and each gate states what it cannot see. Source: the repo’s gate reference and CI workflow, as of 3 October 2026.

One idea, through every station.

An illustration, built from Lendable's public site only. It is not Lendable work. The idea sits where a product designer at a lender spends real time: a person who has just seen a quote, a choice between borrowing now and waiting, and copy that has to keep both open without nudging either way.

Shown at full capacity, the finished factory. What runs today is in section 08.

Illustrative: an idea sketched for the factory, built from Lendable’s public site. Not Lendable work, no inside knowledge.

Rate path

Hypothesis to test People who check their rate and land in the Fair or Limited band either borrow at the highest cost or leave, and neither outcome is good for them or for the lender.

The idea: after a soft-search quote in a higher band, show the total cost in plain pounds next to a better band, the two or three factors that most often move a band, and an opt-in to be quoted again later with another soft search. The person can choose to wait without losing the journey, and borrowing now stays an equal choice.

From the public site only: personal loans of £1,000 to £25,000 over one to five years; “See your rate before you apply - it won’t affect your credit score”; offers set by credit band (Great, Good, Fair, Limited); “committed to responsible lending”.

  1. Step 1: Intake

    Discovery drawer · run package

    Person
    Types the problem as a blank idea, picks the Create PRD posture and states plain facts about the product, such as “a regulator can inspect it”.
    Agent
    Opens a run package and starts on the twelve opening questions. Each stated fact adds its own module of questions, so the regulated module joins the session.

    Artefact

    A run package

    The problem recorded as a problem, never as the answer. A real company’s package stays in a private folder and is never committed to the public repo.

  2. Step 2: Decide

    Question bank · op applier · PRD projection

    Person
    Answers up to 31 questions drawn from a 76-entry, source-backed bank, and parks what belongs in a later version.
    Agent
    Judges each answer against that question’s own weak-answer note and asks again when it is thin. Every decision is one tool call into a pure applier.

    Sample exchange

    Question “What happens today, and how do you know?”

    Weak answer “People in the lower bands drop off.”

    Agent “Drop off where: at the quote, the offer or the drawdown? Which number shows it, by band?”

    Artefact

    prd.md

    Generated from the recorded answers, never written by hand. The decision line:

    Decision: offer a wait-and-re-quote path beside the quote, with borrowing now kept equal.

    Evidence asked for: quote to offer to drawdown, by band. Marked unknown until supplied; the factory asks for it and never invents it.

    Kill criterion: stop if opted-in re-quote uptake, or later approval in a better band, does not beat a stated baseline, or if complaints rise.

  3. Step 3: Company pack

    Per-company brief · derivation engine · ethics gate

    Person
    Writes a company brief with source links, then approves or corrects every proposed value. The agent proposes; the person decides.
    Agent
    Proposes a pack from the brand colours on the public site only. The derivation engine turns it into an accessible palette with WCAG checks and writes down every adjustment it made for contrast.

    Ethics gate The same engine runs the Hooked frequency filter. A loan is taken rarely, so the verdict is utility: get in, do the job, leave, with habit mechanics rejected. Two answers place the idea on the Manipulation Matrix, and the target is facilitator: it improves the person’s life and the maker would use it. Nothing in the flow may nudge towards borrowing.

    Artefact

    A private, derived pack

    • Token values under the shared contract; components are never forked
    • The derivation trace, with each human correction visible
    • The ethics verdict, recorded beside the pack

    It lives only in the private folder and an unlisted instance. This page carries none of Lendable’s logo, fonts or colours.

  4. Step 4: Build on the canvas

    Free canvas · component vocabulary · ledger · ratify

    Person
    Lays out the screens, then the states, and accepts or refuses each agent proposal. Keeps “borrow now” and “wait and re-quote” the same size and weight, with nothing pre-selected.
    Agent
    Composes only from the validated component vocabulary. Anything outside it is refused in the open and logged in the ledger, never filled in silently.

    Artefact

    Screens, each a base plus overrides

    • Quote result in a higher band
    • Total cost beside a better band
    • Factors that move a band
    • Opt in to a later re-quote
    • Re-quote reminder
    • Borrow now anyway, kept equal

    Error and edge states

    • Soft search unavailable
    • Affordability check failed
    • Vulnerable customer: route to a person

    Each state stores only what differs from its base, so a fix to the base reaches every state. The screens are drawn in the product, below.

  5. Step 5: Gates

    Build checks · journey drivers · pixel gate

    Person
    Reads each gate’s result, and runs the browser journeys through the edge states before trusting a green run.
    Agent
    Fixes what the gates name. A bad agent run is fixed with a tighter prompt and a re-run, never a hand edit.

    Artefact

    A gate record: what fires on what

    • Token lint a component on the cost-comparison card asking for a token the contract does not declare
    • Composition a part outside the vocabulary, or a state missing from a lane
    • Journeys the opt-in, the reminder and all three edge states, on Chromium, Firefox and WebKit
    • Pixel any screen that moves against its committed baseline
    • Contrast every token pair at AA: 4.5:1 for text, 3:1 for controls
  6. Step 6: Hand off

    Handoff pack generator

    Person
    Gives engineers the pack, or drags its token file into a Figma variable collection.
    Agent
    Generates the pack from the specs and the build. Nothing in it is edited by hand.

    Artefact

    The handoff pack

    • A ComponentSpec for each part, and a DataContract for the quote, band and total-cost fields
    • Tokens for CSS, iOS and Android
    • The agent vocabulary and an llms.txt index
    • Web Component wrappers, plus the flow, refusals and lineage of the build
    • The Figma import path
  7. Step 7: Show

    Instance builder · replay · trace player

    Person
    Runs the printed deploy command, so the private link goes live only when they choose, and shares it with the one reader it is for.
    Agent
    None in the reader’s browser. The instance replays committed runs, labelled “real run, curated”.

    Artefact

    A private, unlisted instance

    • Noindex, under the derived pack, labelled as speculative work from public statements, sources linked, not affiliated or endorsed
    • The pack derivation replayed, with the human corrections visible
    • The recorded build run replayed on the canvas, step by step
One illustrative idea, Rate path, and the hypothesis its Decide session would test, through the finished factory in seven steps. Each step names the mechanism, what the person does, what the agent does and the artefact it leaves. Source for the code: github.com/linardsb/ux-factory.
Rate path: a breadboard and five key screens. Illustrative. An idea sketched for the factory, built from Lendable’s public site. Not Lendable work, no inside knowledge. Brand, figures and copy are placeholders. Public facts used: personal loans of £1,000 to £25,000 over 1 to 5 years; “See your rate before you apply - it won’t affect your credit score”; offers by credit band, Great, Good, Fair and Limited. The idea: when a soft-search quote lands in Fair or Limited, show the cost in pounds next to a better band, the few things that most often move a band, and an opt-in to be quoted again later. Borrowing now stays an equal choice.

How to read it

  • Underlined items are affordances; the arrow after each names the place it leads to.
  • Data lists the DataContract fields a state needs: quote band, amount, term, total repayable, factors, consent flag.
  • Gate names the factory gate that would check that state. The gates are real; this idea is a sketch, not a committed run.
  1. 1 Quote result in a higher band

    • See the cost next to a better band → 2
    • Continue → 4

    Data quote band, amount, term

    Gate journey driver: Fair and Limited branch here, Great and Good skip to 4

    • Soft search unavailable

      “We couldn’t check your rate just now. Nothing was recorded on your file.” Try again → 1.

      Data amount, term (kept, so nothing is retyped)

      Gate journey driver: the error branch

  2. 2 Cost side by side

    • What moves a band → 3
    • Choose what to do → 4

    Data quote band, amount, term, total repayable (both bands)

    Gate WCAG pair check: both columns at AA, neither band styled as the winner

  3. 3 What moves a band

    • Back to my choice → 4

    Data factors (two or three, from the lender’s own model)

    Gate journey driver: the place returns to 4 with the quote unchanged

  4. 4 Choose: borrow now or re-quote later

    • Borrow now → application
    • Re-quote me later → 5
    • Talk to a person → support

    Data quote band, amount, term, consent flag

    Gate ethics gate (Manipulation Matrix): equal weight, no pre-selected option, no countdown

    • Affordability check failed

      After Borrow now: a plain reason, no offer pushed. Re-quote me later → 5 stays available.

      Data amount, term, consent flag

      Gate journey driver: the decline branch

    • Difficulty or vulnerability signalled

      Reachable from every place. The flow stops selling and routes to a person.

      Data none beyond the session; no band shown

      Gate journey driver: every place has the route

  5. 5 Re-quote reminder

    • Get a new quote → 1
    • Stop reminders → opted out

    Data consent flag (true), amount, term

    Gate ethics gate (frequency filter): a rare event reads as utility, so no streaks or habit hooks

    • Opted out

      Consent off: nothing is sent. One confirmation, “Reminders are off”, and the journey ends.

      Data consent flag (false)

      Gate journey driver: no reminder after opt-out

What runs today, and the target.

Read from the repo on 3 October 2026. Issue and epic numbers point to the evidence on GitHub. The finished state is each epic's own target, as its PRD writes it, not a date.

1
Decide · shipped, follow-on open
Today

Epic #279 closed on 14 September 2026 with its hypothesis read as right. The bank holds 76 questions across nine stages, with a 12-question opening set and five facet modules; 12 run packages are committed. Not met at close: auditability, and the audit run found none of eight known gaps, three in part. Epic #504 is open after all 11 committed PRDs, graded on 22 criteria, lacked a status, decision log, summary, launch plan and acceptance criteria.

Finished state

A discovery session starts in the portal and reaches a PRD in one sitting that an engineer can build from: re-generated PRDs score higher than the committed baseline on the 22 grading criteria, with a decision log and a sign-off line.

2
Build · in progress, epic #295
Today

The free canvas replaced the fixed grid (#302). Five generic primitives landed: stack, text, list, icon and choice. Import from Brilliant and Figma, the compose loop, ratify, and a ledger of what the agent did, refused and corrected are in place. The first validation run, Faster Payment from its PRD (#316), is still open.

Finished state

One real flow built from its PRD on the canvas, with one imported part: Faster Payment across four screens, its Confirmation of Payee states, the safety stop and each send outcome, with a handoff pack out the other end.

3
Hand off · partly shipped, epic #329
Today

The pack is generated and committed: 26 component specs, data contracts, tokens for CSS, iOS and Android, Web Component wrappers, the agent vocabulary and an llms.txt index (#419). The backend seam has six open slices, #331 to #336.

Finished state

A backend engineer wires a real API from the pack with no round trip to design. The PRD counts it as met when a fresh agent run, given only the pack, stands up a service that passes contract-check and logs fewer than three questions for design. The baseline run logged 20.

4
Show · shipped, follow-ups open
Today

The repo holds 14 site pages and two prototypes, behind three closed epics (#164, #202, #243). CodeQL's 14 high alerts were fixed in code, none dismissed. Marking what the agent said against what it did (#496) is open.

Finished state

A public site that replays committed runs, with the gates shown as evidence, and a company brief that compiles to a private, unlisted instance under that company's own pack. No model runs in the reader's browser.

Where the job description shows.

Lines from the job description, each next to where it shows: in ux-factory, or in the prototypes on my portfolio. Kestrel, Meridian and Kettle are invented brands.

01
Flows, prototypes, edge cases and error states

Build stores each state as the base screen plus overrides, and a check fails the build when a declared state is missing. In the prototypes, the heavy month prices every way out of a missed payment with nothing pre-selected, and settled names the interest inside an early settlement figure as its own line.

02
Discovery with product managers and engineers

Decide records each decision with its evidence and kill criterion, so product, engineering and design read the same reasons. In agency work I was the primary client contact for most of my time there.

03
Design system and brand guidelines, inconsistencies flagged

One token contract under every component; token lint fails the build on an undeclared token, and a drift check on a hand-edited generated file. Before this, design systems in Taxi for Email let non-technical marketers assemble on-brand campaigns they could not break.

04
Documented work for engineers and AI tools

The handoff pack: component specs and data contracts from one source, tokens for three platforms, and an llms.txt index telling an agent which file to read and when. The Figma import path is documented; the parity run against a real Figma file has not landed.

05
AI in daily work

Agents propose and people decide, and every run is committed. In the handover, an AI support agent reaches a guidance rule and passes the conversation to a person, who reads the briefing and takes the seat.

06
Accessibility to WCAG AA

On my portfolio, contrast is measured per colour pair against its surface, and the measurement can move the brand value. On a separate concept site, outside ux-factory, axe reported 0 violations across 11 routes in light and dark, with 42 text pairs AA by computation. ux-factory itself has no automated accessibility scanner, and none of this is a screen-reader audit.

07
Fair customer outcomes

switch can tell a customer to stay where they are, and faster payment carries a scam stop written to be read. Rate path keeps borrowing now an equal choice. Designed with Consumer Duty in mind.

08
Mobile product design

ugoki, my own native iOS and Android wellness app, 2026. Before that, years of email built mobile first.

The gap, honestly: no moderated user research or usability testing on my record yet. The prototypes can be tested but have not been tested with customers, and their measures are plans, not analytics I have run. No product designer title in a squad, and no employment in an FCA-regulated firm.