Angelo Rosa — Product Designer

Back to blog

Deterministic Documentation: How I Transformed Design Automation into an Auditable System

Published on

Exploring how to transform tacit knowledge into explicit and auditable processes through a harness architecture for AI-powered UI/UX automation.

Deterministic Documentation: How I Transformed Design Automation into an Auditable System

During operational mapping of a recent project, I realized that the quality of automated work wasn't being limited by the AI's ability to design, but by my inability to communicate precisely what should be done. Each session with Claude was a negotiation. Every result was a surprise. Every correction was a step backward.

This led me to a fundamental question: how do other disciplines (like software engineering) solve this problem of scale and quality? The answer came quickly: through deterministic documentation. Not documentation as a passive record of what was done, but as an active specification of what should be done.

I spent my vacation studying agent architecture and automation systems. The result was building a Figma harness that transforms tacit decisions into explicit, auditable, and repeatable processes. But the real learning was this: documentation isn't an artifact you create afterward. It's the structure that enables automation to work.

The Real Problem: Tacit vs. Explicit Knowledge

When you work in product design for over a decade, you accumulate knowledge that isn't written anywhere. You know, for example, that a "ghost" button is different from a "destructive" button not just visually, but semantically. You know when to reuse a component and when to create a new one. You know how to maintain coherence across a multi-screen journey.

This knowledge lives in your head. And as long as it stays there, it can't be transferred, audited, or scaled.

AI suffers from the same problem as a newly hired junior: it doesn't have access to this tacit knowledge. When you ask it to "build a screen," it makes a series of assumptions. Some are right. Others aren't. And you spend hours reviewing to fix what could have been specified from the start.

The solution isn't better prompts. It's transforming tacit knowledge into explicit knowledge through structured documentation.

Documentation Architecture: Engine vs. Content

The first decision was to separate what's universal from what's specific. In the harness I built, this separation is physical:

The Engine encompasses process rules valid for any client. This includes the CLAUDE.md file (which defines how agents should work), component templates, technical standards, and reusable procedures. When I learn something that improves the wireframe interpretation process, it becomes an Engine improvement that benefits all projects.

The Content lives in client-isolated directories, containing the specific design system, decisions made, project learnings, and journey states. This ensures that one client's knowledge never leaks to another.

This separation is crucial because it allows operating multiple clients with the same harness without mixing context. More importantly, it allows the Engine to evolve independently, transforming point fixes into systemic improvements.

The Five Agents and Separation of Responsibilities

The initial temptation was to have a single agent doing everything: "read the wireframe and build the screen." The problem is that this mixes two responsibilities that need to be separable: deciding what to build and executing the construction.

If the same agent decides and executes in one breath, there's no checkpoint in between. An interpretation error automatically becomes an execution error, with no chance for review.

That's why I structured the harness with five specialized agents, each with restricted scope:

The Interpreter receives wireframes and user stories. Its only responsibility is deciding what to build. It doesn't build anything. It analyzes each wireframe element and asks: does this element already exist as a component? Can I reuse it directly? Is it similar enough to create a variant? Or is it truly new?

But here's the critical detail: the Interpreter doesn't just decide. It documents why it decided. It lists which components it considered and why it rejected them. This documentation is visible for human approval before any construction happens.

The Builder executes exactly what the Interpreter decided. It has write permission to Figma and builds one screen at a time. But it doesn't decide anything. It receives a structured plan and executes it. If the plan is wrong, that's not its fault. The checkpoint already passed.

The Documenter records what was built in Markdown files. It transforms implicit knowledge into explicit knowledge. But it only works with validated components, never with drafts.

The Auditor verifies technical consistency. It asks: are tokens hardcoded? Is the nomenclature correct? Are there duplicate components? It works with technical standards documented in COMPONENT_STANDARDS.md.

The Validator verifies that the final result meets the semantic objective of the journey. It asks: do the built screens solve the problem the wireframe and user story describe? Is there coherence between screens? It works with the user story and original wireframe as reference.

Separation of responsibilities isn't just organizational. It's technical. Claude Code has an important restriction: subagents can't confirm interactive approval prompts. This means any write tool used by a subagent is treated as an action that must be explicitly pre-approved. This technical restriction naturally validates the decision/execution separation.

Reuse Logic: Avoiding Component Duplication

The core of the harness's efficiency is its ability to prevent component duplication. This is the real pain I see in legacy projects: 15 variations of a button that should have 3, components with different names doing the same thing, confusing nomenclature.

Three Layers of Decision

For each wireframe element, the Interpreter evaluates three layers of correspondence against already-documented components:

Structural: Does the element have the same internal composition as an existing component? The same sub-elements in the same arrangement?

Functional: Does it have the same purpose within the journey? Does it solve the same type of problem?

Variant Covered: Does the difference found (a state, different content) already exist as a documented variant, or is it new?

The result of this evaluation always falls into one of three categories:

This discipline only works because there's a fixed component documentation template. Each component has specific fields like "When to use," "When NOT to use," and "Related components." These are exactly the fields the Interpreter consults to decide if a candidate works.

Without this structured documentation, the Interpreter would have to guess. With it, it decides based on explicit criteria.

Memory: Transforming Volatility into Persistence

Claude retains nothing between sessions by default. Each new conversation starts from zero. This is a fundamental problem for long-term automation: how do you ensure that a fix made today won't be repeated as an error tomorrow?

Memory: Volatile vs. Persistent

The solution is simple: everything that needs to persist becomes a versioned file.

Journey-state.md is the short-term memory of a journey. When the Builder builds the first screen, it reports what it did in text. I (or the main session) record this report in journey-state.md. When the Builder is called again for the second screen, it receives the updated journey-state.md as part of the context. This ensures the same type of element is resolved consistently across different screens.

Memory/decisions.md records non-obvious decisions. For example: "use ghost variant, not destructive, per client request." This prevents the same fix from being made repeatedly in future sessions.

Memory/learnings.md captures patterns that repeat and deserve to become permanent rules. If we discover that form components always need a specific label, that becomes an Engine rule, not a repeated decision.

Memory/component-changelog.md is the chronological history of official component creation and modification. It's not just a record, it's an audit trail.

This approach transforms every fix made today into a rule that prevents the same error tomorrow. Documentation isn't a passive artifact. It's the living structure that enables the system to learn.

The Order of Things: Why Validator Comes Before Documenter

This ordering decision seems small but avoids a serious problem. If the Documenter recorded a new component in the design system right after the Builder created it, before any semantic validation, there's a risk of formalizing a component born from a wireframe misinterpretation.

Once official, that component would be offered as a reuse option in future tasks, propagating the error.

That's why there's an intermediate stage: new components first enter design-system/components/_draft/ (draft). They exist in Figma and are documented, but aren't offered by the Interpreter as a reuse option until promoted to the official folder, which only happens after Validator approval.

This order isn't arbitrary. It's a barrier preventing interpretation errors from becoming permanent parts of the design system.

Technical Standards: Making Components Machine-Readable

Documenting what a component is (name, variants, tokens) isn't enough. You need to ensure it was built in a way that allows the model (and MCP) to recognize it reliably.

Components Machine-Readable

That's why there's a COMPONENT_STANDARDS.md file with rules like:

These standards don't exist to satisfy technical purism. They exist because they make components readable to the harness. Without them, even with good Markdown documentation, the actual Figma could be built in a way the MCP can't reliably interpret.

Technical documentation isn't a luxury. It's a functional necessity.

Isolation and Security: Documentation as Barrier

Since the Figma account is a single corporate account with each client's projects organized internally within it, client isolation isn't done through separate credentials. It's done through configuration and documentation.

Each project has a PROJECT.md file explicitly declaring that client's Figma file-key. Before any write operation, the Builder confirms the destination matches the declared file-key. If it doesn't match, it stops and alerts. Never proceeds.

This means protection against "writing to the wrong project" is a documented process rule, not a technical permission barrier. It requires discipline, but it's sufficient given there's a single token.

Project memory (decisions, learnings, changelog) is always project-isolated, never shared between clients, for confidentiality reasons. This isolation is also documented.

What Was Left Out: Conscious Decisions

Not every identified gap needs to be solved now. Some decisions were deliberately deferred, with trade-offs already recorded:

Onboarding disorganized legacy design systems is treated as a completely separate project with its own process, because it has very different cadence and risk from everyday harness use.

Automated Figma rollback is manual via native history. The draft/official stage already greatly reduces the need for this.

Multiple approvers: for now, a single human approves. But the field already exists in records to facilitate future expansion without format rework.

Responsiveness / breakpoints: field already planned in the component template, but no functional process until there's a real case that requires it.

These decisions aren't weaknesses. They're recognitions that perfection is the enemy of functional. The documentation makes clear what was left out and why, allowing future iterations to be informed.

Conclusion: Documentation as Infrastructure

Design automation doesn't fail because AI can't design. It fails because the knowledge that should guide the AI is stuck in people's heads. Transforming that tacit knowledge into explicit, structured, auditable knowledge is the real work.

Deterministic documentation isn't an artifact you create after automating. It's the infrastructure that enables automation to work. It's what transforms AI from an unpredictable tool into a deterministic execution engine.

The designer's role is changing. We're moving from being pixel artisans to becoming systems architects. And documentation is the building material.