June 26, 2026 · updated September 14, 2026 · 8 min read
Original version, written in English.
Judgment is a harness property
What AI agents are missing is no longer intelligence. What is missing is judgment, and I think this ability is mostly granted by the harness. In this article, I explain how I built mine.
In April 2026, I had a business idea and wanted to experiment with AI. Since then, I built the product using an autonomous pipeline of AI agents. I didn't write a single line of code, and my product is now live, fully functional, and used by real customers.
That product is Tablia, a reservation platform for restaurants that covers all the needs of restaurateurs: a booking widget, a back office, and guest notifications. It has a consistent tone of voice, a solid graphical identity, and everything is implemented according to strict code standards. My goal was to keep the codebase maintainable, testable, and scalable, unlike most of today's vibe-coded products. You might ask: how did I do it?
I will address that in this article, where I explain the thesis I had in April 2026 right before starting, and most importantly, how the past months validated and even surpassed what I thought was possible.
Judgment is the true bottleneck.
I don't think I need to convince you that models are now intelligent enough. Erdős problems and Navier-Stokes questions have seen major breakthroughs, yet human input is still required in companies to get actual work done. So what is missing?
Let me give you an example. When I shipped my landing page, I asked the agent to ship it with no horizontal overflow. It ended up applying a fixed 56px side padding across every screen width. On a 390px mobile phone, that left a 183px column of text, about 25 characters per line.
Any human spots the problem in a second because they have the context and common sense to evaluate the page. Agents do not have that. Instead, they do their best to follow instructions literally. If they do not know the page needs to display well on small devices, they will not consider that possibility, especially when asked to avoid horizontal overflow. You probably had similar experiences, and it forces you into exhausting mental gymnastics every time you write a prompt to make sure it contains all required instructions.
That is exactly where contextual judgment comes in. AI models lack this because they are built to be agnostic and broadly useful across any domain.
However, this can be solved by providing that context, clear guidelines, and ways to verify work directly inside the harness. Those are the three pillars: context, process, and verification.
Pillar 1: Context
Context aims to help AI agents understand their mission. If an agent starts with all the context of your company, stored in text files it can access, it can theoretically make decisions just like you would. It shares your knowledge, constraints, and goals.
That is what I implemented using an iterative loop in every Claude session to build persistent memory for my company's agents.
Concretely, it is a documentation tree that I treat as infrastructure for the agents. Today it holds 111 decision records, 120 tracked actions, 113 processed conversation memories, 26 feature briefs, and 24 acceptance-test files. Every decision, product rationale, convention, and task lives there, not in my head or in a chat history.
I call this memory tree an infrastructure because it is not just a folder full of random documents. It is a versioned tree containing only relevant information accessible through indexes. Every folder has a README that indexes its contents in one line per entry. An agent reads the index first and opens only what it needs, following progressive disclosure. The index of decision records alone is detailed enough that an agent can navigate to the right record without opening a single file.
Keeping this tree alive and updating it with new information is the real challenge. I solved it with a two-step loop. After every working session, a /memorize command saves the conversation while preserving my inputs verbatim. The instructions for this skill state that my inputs are the source of truth and must not be paraphrased, because they are the alignment signal everything else comes from.
See the /memorize command definition (simplified)
# Memorize Conversation You are memorizing this conversation into the project's documentation infrastructure. This is a critical operation: the user's inputs are gold -- preserve them precisely and completely. Do not summarize, paraphrase, or lose any information the user provided. ## Instructions ### Step 1: Capture uncommitted changes Check if there are uncommitted changes in the repository: - Run `git status` to see the current state - If there are uncommitted changes, create a commit with a descriptive message - Record the commit hash(es) created ### Step 2: Gather conversation context Analyze this entire conversation and extract: 1. **User inputs** (verbatim -- do NOT summarize or paraphrase these) 2. **What was done** during the conversation: - Code changes made (files created/modified, commit hashes) - Infrastructure actions (services deployed, domains configured, etc.) - Decisions taken and their rationale - Research performed - Plans discussed - Tools/services set up - Any other notable actions or outcomes 3. **Date** of the conversation ### Step 3: Create the raw memory file Create a file in `docs/raw/` with the naming convention: ``` docs/raw/YYYY-MM-DD-<short-descriptive-slug>.md ``` The file MUST follow this structure: ```markdown # <Conversation Title> **Date:** YYYY-MM-DD **Status:** unprocessed ## User Inputs > [Preserve EVERY user message verbatim, in order, as blockquotes. > Each message separated by a horizontal rule. > This is the most important section -- lose nothing.] --- ## Actions Performed ### Commits Created - `<hash>` - <commit message> ### Code Changes - <description of changes> ### Infrastructure Changes - <servers, domains, deployments, services, etc.> ### Decisions Made - <decision>: <rationale> ### Research Conducted - <topic>: <key findings summary> ### Other Actions - <anything else notable> ## Key Information Extracted <Bullet points of critical facts, numbers, names, URLs, configurations, or any specific information the user provided that must not be lost> ## Topics for Processing <List which docs/ subfolders should be updated when this memory is processed:> - [ ] actions/ - <if actionable items were discussed, planned, or status changed> - [ ] decisions/ - <if decisions were made> - [ ] motivations/ - <if motivations/vision were discussed> - [ ] research/ - <if research was conducted> - [ ] architecture/ - <if architecture was discussed> - [ ] specs/ - <if requirements or designs were discussed> - [ ] qa/ - <if the test strategy was discussed> ``` ### Step 4: Confirm After creating the file: - Show the user the path of the created memory file - Show a brief summary of what was captured - List any commits that were created as part of the memorization - Remind the user they can run `/process` to integrate this into the structured documentation
A second command, /process, then integrates that raw memory into the structured docs. It has to find the right place for any information and update the indexes.
See the /process command definition (simplified)
# Process Raw Memories
You are processing unprocessed raw conversation memories from `docs/raw/` into the project's structured documentation. This is how the project's knowledge base evolves and stays current.
## Instructions
### Step 1: Find unprocessed memories
List files in `docs/raw/` (excluding the `processed/` subfolder and `README.md`). These are the unprocessed memories. If there are none, tell the user and stop.
### Step 2: Read and analyze each memory
For each unprocessed memory file:
1. Read the full content
2. Identify the "Topics for Processing" section which flags which docs/ subfolders need updates
3. Analyze the User Inputs and Actions Performed sections for extractable knowledge
### Step 3: Update structured documentation
For each topic area flagged, update or create documents in the corresponding folder. **The format law below is binding for every write.** Read `docs/README.md` if you need the full statement of it.
#### The format law (applies to every doc and every index you touch)
Three storeys: the folder README routes, the doc carries its own summary, the archive holds what is inactive.
1. **The doc carries its own summary.** Every `.md` you create or update starts with YAML frontmatter (`status`, `date`, a `description` of at most 300 characters, plus `supersedes` / `superseded_by` when it evolves a prior doc), then the H1 title, then a `## TL;DR` section (target <=20 lines, bullets). Docs longer than 100 lines also get a `## Contents` TOC (one line per H2/H3) right after the TL;DR.
2. **Index entries are ONE physical line, target <=450 chars**, in this shape:
```markdown
- [Title](file.md) - what it decides/tracks + when to open it (trigger keywords) · status · YYYY-MM-DD
```
Descriptions are for **selection, not information**: front-load the trigger keywords an agent would grep for. **Rich summaries NEVER go in an index**: they go in the target doc's `## TL;DR`. If you find yourself writing a paragraph in a README, you are writing it in the wrong file.
3. **Nothing is destroyed.** Content you remove from an index MUST land in the target doc's TL;DR first. Move, never drop. The user's verbatim quotes stay in their original language, byte-for-byte.
4. **Budgets.** Every `README.md` under `docs/`: **<=200 lines AND <=25 KB**. When a README approaches the budget, archive inactive entries. Never delete live ones, never shorten by dropping, and never compact live descriptions: raise the breach to the user instead.
#### `docs/actions/` - the board (open items only)
- **When**: Actionable items were discussed, planned, assigned, or their status changed
- **Action**: Create `docs/actions/YYYY-MM-DD-<slug>.md`, or update the existing file when the action already exists (status change, new acceptance criteria, new origin note)
- **Content**: frontmatter (`status: to-refine|pending|in-progress|to-validate|done` / `date` / `updated` / `description`) + H1 + `## TL;DR` (origin, the user's verbatim words, acceptance criteria, links) + the body
- **Index**: `docs/actions/README.md` is a board of **OPEN items only**. Move the one-line entry between status groups as the status changes.
- **On flip to `done`**: set `status: done` + `updated:` in the frontmatter, `git mv` the file to `docs/actions/archive/`, delete its line from the board, and add one cold line to `docs/actions/archive/README.md`. A `status: done` file must never sit directly under `docs/actions/`.
#### `docs/decisions/` - theme folders
- **When**: A decision was made during the conversation (technology choice, architecture direction, product feature scope, strategic pivot, etc.)
- **Action**: Classify the decision into exactly one theme folder (for example `product`, `engineering`, `design`, `process`, `infra`), then create `docs/decisions/<theme>/YYYY-MM-DD-<slug>.md`. `docs/decisions/README.md` carries the routing table: read it to route; only touch it when a theme's scope itself changes.
- **Content**: frontmatter (`status: accepted|superseded` / `date` / `theme` / `description`, plus `supersedes` / `superseded_by` when it evolves a prior decision) + H1 + `## TL;DR` + context, decision, rationale, alternatives considered, consequences.
- **Superseding**: when this decision replaces an earlier one, set `superseded_by:` on the old record, flip its `status: superseded`, and move its line out of the theme README's hot index (keep a one-line pointer noting what superseded it).
- **Index**: add ONE line to `docs/decisions/<theme>/README.md`.
- **DIGEST**: when the theme has a `DIGEST.md` (the standing rules of that theme), update it too: one bullet (<=3 lines), the rule as an **imperative sentence** + link to its record. No rationale, no history. If the new decision supersedes a rule, **replace** the old bullet; superseded rules never appear in a digest. Skip the digest for pure one-off outcomes that constrain nothing going forward.
#### `docs/features/` - feature bundles + the registry
- **When**: A feature shipped, changed status, or gained/changed a durable artifact (brief, requirements, design brief, plan, test scenarios)
- **Action**: Everything for a feature lives in `docs/features/<slug>/`: `brief.md`, `prd.md`, `design.md`, `plan.md`, `scenarios.feature`, plus `run/` for pipeline working matter (feedback rounds, reviews, defects, screenshots). Update the artifact in place; keep the frontmatter `status:` current (`specced` -> `in-progress` -> `shipped`).
- **Index**: `docs/features/README.md` is the registry: **one line per feature**, ordered by ship date (unshipped last). New feature => new line; when a feature ships, update its line (status + date).
#### `docs/motivations/`
- **When**: The user described new motivations, vision changes, strategic goals, or explained WHY something matters
- **Action**: Update existing motivation documents or create new ones
- **Content**: Preserve the user's intent precisely -- this drives all downstream decisions. Their verbatim words stay in their original language, byte-for-byte.
- **Update the Index** in `docs/motivations/README.md` (one line per entry)
#### `docs/research/`
- **When**: Research was conducted or requested -- market analysis, technical investigation, competitive intelligence
- **Action**: Create a research document or update an existing one. Move detailed research reports here if they were created elsewhere in the repo
- **Content**: Objective, methodology, findings, implications for the project
- **Update the Index** in `docs/research/README.md` (one line per entry)
#### `docs/architecture/`
- **When**: Architecture was discussed, codebase structure changed, infrastructure was set up, technical specifics were documented
- **Action**: Create or update architecture documents
- **Content**: System design, component interactions, infrastructure topology, codebase conventions, deployment specifics
- **Update the Index** in `docs/architecture/README.md` (one line per entry)
#### `docs/qa/` - transversal only
- **When**: The **cross-feature** test strategy changed (layers, tagging, authority model, tooling)
- **Action**: Update `docs/qa/test-strategy.md`. Per-feature scenarios do NOT live here: they are `docs/features/<slug>/scenarios.feature`.
- **Update the Index** in `docs/qa/README.md`
#### `docs/specs/` - transversal only
- **When**: The product's global identity (visual identity, design brief) or the initial-features boundary changed
- **Action**: Update the transversal spec documents. Per-feature requirements and design briefs do NOT live here: they are `docs/features/<slug>/{prd,design}.md`.
- **Update the Index** in `docs/specs/README.md`
### Step 4: Move to processed
After fully processing a memory:
1. Add a processing log at the bottom of the raw memory file:
```markdown
---
## Processing Log
- **Processed on:** YYYY-MM-DD
- **Documents updated:**
- `docs/<path>` - <what was updated>
- **Documents created:**
- `docs/<path>` - <what was created>
```
2. Move the file from `docs/raw/` to `docs/raw/processed/`
3. Update the index in `docs/raw/README.md` (remove entry)
4. Update the index in `docs/raw/processed/README.md` (add entry)
### Step 5: Lint gate (mandatory -- every run)
Run the docs linter and make it pass before reporting. It enforces the format law mechanically: README budgets (<=200 lines, <=25 KB), index entry lines <=450 chars, frontmatter presence + `description:` <=300 chars, every markdown link under `docs/` resolving, no `status: done` file directly under `docs/actions/`, and every accepted decision linked from its theme's DIGEST.
**A budget error is NOT yours to absorb: STOP and raise it to the user.** Never shorten the descriptions of live index entries to buy headroom: those lines are the retrieval layer, and detail deleted there is detail no future agent finds. A README over budget means the collection has outgrown its container. Report it with the numbers (how many entries, of what kind, how many never touched since filed) and let the user choose the remedy. You MAY still archive genuinely inactive entries, and you MAY move an entry's substance into its target doc's `## TL;DR` before shortening the line (the "move, never drop" procedure). Other errors (a missing `description:`, a broken link, a `status: done` file left under `actions/`) are yours to fix directly. If a violation is not mechanical (a genuine content conflict, a missing doc), surface it in the report instead of guessing.
### Step 6: Report
Show the user:
- How many memories were processed
- What documents were created or updated (with paths)
- Which index / DIGEST / registry lines changed, and which actions were archived
- The lint result
- Any items that could not be processed and why
### Important guidelines
- **Preserve the user's intent**: When their words describe motivations or vision, preserve the meaning precisely. These are strategic inputs, not just information. Their verbatim quotes stay in their original language, byte-for-byte -- never translate, paraphrase, or trim them.
- **Evolve, don't replace**: Update existing documents rather than creating duplicates. Add new sections, update outdated information, extend existing content.
- **Index everything, once, in one line**: Every document is referenced from exactly one hot index (its folder README, or the archive README once inactive), as a single <=450-char line. The substance lives in the doc's `## TL;DR`, never in the index.
- **Move, never drop**: Anything you remove from an index must already exist in the target doc's TL;DR.
- **Cross-reference**: When a decision relates to architecture, or a feature relates to a decision, add cross-references between documents (repo-relative paths).
- **Be comprehensive but concise**: Extract all actionable knowledge, but keep documents scannable with headers and bullet points.
The overall process looks like this:
Context leads to alignment, but once agents are aligned, they still need to know how to work.
Pillar 2: Processes
An agent with context can make decisions aligned with the organization. But you should not give a huge, ambiguous task to an agent without giving it a method. Think about your best coworker: even if they are very smart, they will struggle with a task whose scope is too broad. What makes them effective is a well-defined scope where they can make decisions, execute with their methods, and hand off the work cleanly to the next person.
That is what I built to implement the product: an autonomous pipeline with 6 steps and 7 agents, each with a clear scope and sequential methods.
The goal is divide and conquer. Implementing a complex feature is difficult for one agent, but straightforward when split properly across specialized agents.
Let's look at an example: implementing customization for the reservation widget and automated messages sent to restaurant customers.
First step: Brief
I write a brief with high-level expectations for the feature. A general-purpose agent ingests my intent, understands it using the project context, and translates it into a structured brief.
Second step: Specifications
An iterative loop between a product agent writing low-level requirements and a designer thinking about how those requirements should look and feel. For example, the product agent determines which parts of the widget should be customizable, and the designer determines how to let the restaurateur do that smoothly. In the end, I get detailed specs, user stories, and a design brief.
Third step: Technical specifications
The staff engineer reads the specs and brief, then determines how the feature should be built according to the codebase and architecture guidelines. It finds solutions to open questions like which providers to use, how to call them, the API contracts between back and front, and the implementation tasks for the software engineer agent. If a problem has no existing guideline, the staff engineer creates a new rule and documents it in an ADR so future tasks follow it. In our case, a guideline could address how the system should save and serve the configuration of each widget.
Fourth step: QA scenarios
Probably the most important step, which we will revisit below. The goal is to set up scenarios the software engineer agent can use to test its work at every stage. It reads the specs and briefs to create three kinds of test scenarios: E2E tests, integration tests, and unit tests. This step depends on implementation details, which is why it runs right after the staff engineer.
Fifth step: Build
The software engineer agent takes the scenarios, technical specifications, tasks, product specs, and design brief to implement the feature. It relies on BDD, meaning every task must be verified against the expected behavior of the product.
Sixth step: Review
Four agents inspect the code and iterate with the software engineer agent until no defects remain across four areas: non-regression, feature completeness, code standards, and visual QA.
You've probably noticed that out of the 6 steps of this pipeline, only one actually writes production code. All the earlier steps exist to remove ambiguity so the software engineer agent can focus purely on executing the decisions made upstream.
And out of these 7 agents, 3 are dedicated to defining how the agent verifies its work. Even if the software engineer agent has context and good methods, it will still introduce defects that must be caught during implementation. That brings us to the third pillar: verification.
Pillar 3: Verification
This is the most important pillar in my opinion. Setting objectives works, but it becomes far more reliable when the agent has a deterministic way to verify whether it completed the job.
I implemented this using two frameworks.
First, the QA and software engineer agents collaborate using BDD. A green test suite means the product matches the specifications. Of course, testing every single pixel is impossible because it would require too much compute, so I balance three types of tests:
- Unit tests: Kept rare because they couple closely to internal architecture, but useful for stable business logic that will not change often.
- Integration tests: The majority of the suite, verifying the actual backend behavior of the application.
- E2E tests: Running against the full stack with Playwright to ensure the frontend interacts properly with the backend.
The second framework is the four-lens review. Each lens enforces code quality around one specific aspect: non-regression, feature completeness, code standards, and visual QA. Visual QA is particularly useful here. Its job is to confirm that the implemented UI matches the design brief. The agent uses Playwright to navigate the app and inspect screenshots to detect visual defects.
Results
Overall, I ran 41 complete pipelines to build the product, mostly in parallel overnight with autonomous deployment.
I had zero production incidents, no critical bugs aside from a few minor UI flaws, and in 9 out of 10 cases, I was impressed by how clean and thorough the implementation was.
What transfers to other organizations, in my opinion
Transposed to any other organization, I believe these three principles hold true:
- Write decisions where agents can read them. Context infrastructure beats prompt-stuffing, and an index an agent can navigate beats a massive pile of files.
- Give every agent a clear method and a well-scoped task so it can do its best work.
- Pair every task with a way to verify it was completed successfully.
Intelligence is abundant now. What will set organizations apart is the judgment they build around it.
What is the next bottleneck?
Intelligence plus judgment takes care of product development. So what is left?
Acquisition.
That means earning trust from other humans, which is a problem AI has not solved yet. It is also why I do not have thousands of customers at this point. Stay tuned for the next part of my journey: building an acquisition pipeline using this exact same approach.
Ciao 👋