The agent writes: "Done, all tests pass." Then I have two options: believe or show someone who knows. There is no one to show. There is no developer in the project, and I don't read code.
I am a product person. Since January, I have been making a Chrome extension, and now the Chrome Web Store version is 1.0.1. All the code was written by two AI agents, Claude Code and Codex. The same agent that wrote the code also wrote the tests, so passing tests on their own don't prove anything. Why I trust them and when I don't is lesson 3.
Over these months, I have started requiring more from the agent than just the message "done":
checks that fail if a rule is violated;
a report of what the agent saw in the browser;
a step-by-step process of how I manage the task: from discussion to acceptance.
Models have also become smarter over this time. How much the results have improved due to them, and how much due to the setup, I haven't measured. Next, I'll explain how I set up the checks and work with the agent:
Wrapper. Rules, checks, prohibitions, and skills around the agent. Nine lessons with dates from the project's history.
How I work with her. Six steps from idea to acceptance and the prompts I insert into the agent at each step.
What I will change in the next project. Five improvements. Each has a counter-argument.
Questions for you.
I have posted the harness as an open template - a set of files that anyone can take: https://github.com/yesgenius/agent-harness. It includes everything that will be discussed in the first part and a demonstration. It breaks a copy of the project in 42 ways and shows which check caught each break. On my computer it takes less than a minute.
The template is entirely in English, and this keeps the watchdog: a line with letters not from the Latin alphabet breaks the tests. The agent talks to you in the language you write to it. How to read its pages in Russian directly on GitHub is explained in the section "How to try the template".
On what it was tested
The harness grew by one product - a Chrome extension called Chat with Multiple AI. It sends one request at once to 15 AI chatrooms: ChatGPT, Claude, Gemini, and others.
These chats are foreign websites, and they change without warning. Therefore, the description of how to work with each chat is in a separate settings file. When the chat changes, I correct this file, and the correction reaches users without a new version in the store.
What has already been done:
two versions in Chrome Web Store;
two corrections of this file, October 19 and November 1;
70 acceptance scenarios that the agent went through in the browser before version 1.0.1.
Words that will be encountered
Terms collected under spoiler. These are not strict definitions, but what each word means in this article and my project. Where the word is my translation of an English term, it is marked.
DictionaryWord | What it means |
|---|---|
Agent | AI that not only answers but also works in your project folder: reads and changes files, runs programs |
Branch | Separate line of the project's history. My development is in one branch, and the release version lives in another |
Diff | List of modified lines: what was and what became |
Green, failed | Green check passed. The crash found a violation and stopped the work |
Commit | One entry in the history: what changed, who, and when it was done |
Console | Browser's developer panel where logs are visible |
Context | All that the agent keeps in memory during the current session: chat messages and read files. The volume is limited. When the context is full, the agent starts getting confused |
Configuration | Here: a settings file separate from the code. My extension downloads it and reads how to work with each chat |
Log | Log where the program writes what it does |
Model | AI inside the agent |
Work order (work order) | My work order translation. Task assigned to the agent: what should result and how to verify it |
Harness (harness) | Here: everything surrounding the agent in my project: AGENTS.md, checks, restrictions, skills |
Provider | Here: external service that the product relies on My chats with AI |
Prompt | Text for the agent's task |
Push | Sending new commits to GitHub |
Extension | Chrome browser add-on |
Review | Reviewing someone else's work. A reviewer is someone who checks |
Repository | Project folder along with this history |
Build | I have: one run that prepares the project and runs quick automated checks. Tests and monitors are started with a separate command |
Session | Here: one chat with an agent. A new session does not remember the previous chat |
Context compression | When the context is filled, the agent briefly recounts the chat content and continues working with this summary. The place is still there, but the chat details are lost |
Skill | File with instructions for the agent on a single repeatable action, for example commit |
Slice | Here: a thin slice of a new feature that runs through the entire product and gives a visible result |
Specification | Here: a document in the project that records how the product should work |
Guard (guard) | My translation for guard, which is called in the template. A test that protects the project rule: a commitment to the user or the workflow order. The name of the guard is the rule itself, written as a phrase |
Test | A small program that runs a piece of the product and compares the result with the expected one |
AGENTS.md | File with project rules for the agent. It is read by both Claude Code and Codex |
Chrome Web Store, store | Chrome Extensions Store |
Claude Code, Codex | Two such agents, from Anthropic and OpenAI. Both have a computer application with a regular chat |
Git | A program that stores the entire history of project changes |
GitHub | A site for storing projects and their history. I have a copy of the repository there |
Part 1. Wrapping
Who checks what
I set the acceptance criteria, and the wrapping checks help find errors that would otherwise have to be searched in the code.
Here's how my checks are divided:
Who checks | What checks |
|---|---|
Build, tests, and guards | Rules written in code and documents, and that the code and documents are aligned |
Agent in the browser | What the product actually does |
Independent reviewer | Diff written by someone else |
I | Visible behavior according to the list from the report. And I decide what to build |
Some rules are written only in AGENTS.md, and the agent may violate them. How I work with this, I'll tell in the second part.
1. AGENTS.md does not stop the agent
On February 2nd, a file with agent rules appeared in the project. It contained:
general principles such as KISS ("Keep It Simple") and DRY ("Don't Repeat Yourself");
a list of technologies;
folder structure.
In March, a rule "no magic numbers" was added. A magic number is a number in the code whose meaning is never named anywhere: for example, 3600 instead of "one hour". The file grew: 61 lines in February, 179 in October.
The agent could violate any of these rules, and without checking, I wouldn't have known. The first watchdog appeared only on May 11th.
I'll show with an example why a single text is insufficient. My product promises: if I fix the configuration file, the extension checks it no less than once an hour. How often the extension re-reads this file is determined by a single number in the code.
Suppose the agent changed hours to days. The test took the new number from the same code, compared it with itself, and was satisfied. I look: everything is green. The user waits for a day. According to the green test, it seems the frequency is under control. Although the limit "no less than once an hour" is not even set in it. A watchdog is needed here: a test that checks the interval is not more than an hour. In this watchdog, there are two comparisons:
test('the configuration is read at least once an hour', () => { assert.ok(PROVIDER_CONFIG_REFRESH_MS > 0); assert.ok(PROVIDER_CONFIG_REFRESH_MS <= ONE_HOUR_MS); });How to read this:
in quotes the name of the watchdog: "configuration is read at least once every hour";
PROVIDER_CONFIG_REFRESH_MS - that very number: how often to re-read the settings file, in milliseconds;
ONE_HOUR_MS - one hour in milliseconds;
assert.ok means "must be true": the number is greater than zero and not more than an hour.
If the agent sets a day, the second requirement will not be fulfilled, and the watchdog will fail.
The watchdog holds exactly what is written as the number - the frequency. It does not check whether the program actually downloads the file. The example is taken from a template, and the template does not have a section of code that re-reads the file, while the watchdog keeps the promise to the user "it's time to re-read".
The watchdog's filename is the promise itself, written as a regular phrase. Therefore, the list of files is read as a list of product promises:
a-published-provider-fix-reaches-a-user-within-an-hour no-reminder-leaves-before-the-intent-is-recorded no-provider-name-outlives-the-provider-configIn other words:
A published provider fix reaches a user within an hour.
Reminder does not leave until it is recorded that it is going to be sent. Without this record, the product won't know after a restart that it already sent it and will send it again.
The provider's name appears only in the settings file: it's not in the code, tests, or documents. The service changes without warning, and the line with its name outside the settings file would continue to describe something that no longer exists.
I currently have 89 guards. The most guards were added in August and September:
Month | New Guards |
|---|---|
May | 2 |
July | 9 |
August | 33 |
September | 40 |
October | 5 |
What to request from the agent in your project:
Product promise:Replace the angle brackets with your own promise. You need to check two things: the guard's name sounds like your promise, and the failure is indeed shown.
2. Two copies of the rules must necessarily diverge
Claude Code and Codex read rules from different files. Therefore, since February I had two rule files, CLAUDE.md for Claude Code and AGENTS.md for Codex, and they were supposed to be exactly the same. Every rule had to be written twice. It seemed nothing complicated: fix one file, fix the other. But discrepancies accumulated:
When | the lines diverged |
|---|---|
March | 9 |
June | 12 |
August 10 | 21 (lines 102 and 85 in the files) |
The second file was sometimes forgotten, and it only surfaced during tests. At the same time, the second copy didn't add anything new: it was the same rules again.
On September 25, I left one file. Now, the watchdog fails if someone creates:
CLAUDE.md next to AGENTS.md;
a separate rules file in a subfolder;
a file under a backup name, which the agent would also read as rules.
Each agent's skills are in their own folder, so each skill is written twice. The guard checks each pair and fails if the texts differ.
I now treat other copies of the rules the same way:
keeping the rule in one place;
delegating the machine to compare copies and fail if they differ.
3. The green build may not check anything
I have a program that looks for type errors in the code. A type error is when the code confuses data types, for example, treating text as a number. On July 27th, the counter of such errors reached zero.
Zero can be achieved in two ways:
fixing all errors;
stopping looking for them.
From the outside, the result is the same. But stopping the search is easy, just one line:
disable strict checking mode, and it will start overlooking more;
add a folder that the check does not look into.
The build remains green. On July 27th, I recorded in the project history: zero errors can be trusted as long as the check is searching for them in the same scope and with the same strictness.
I have two approaches against this.
Minimum threshold. The check counts how many files it has read, and fails if there are fewer than the threshold. Otherwise, the failure may go unnoticed: the check found no files, found no errors, and reported success.
Intentional break. In the copy of the project, the rule is deliberately broken, and the guard is supposed to fail. If it remains green, it means the guard is overlooking such a violation. In the template, each such error breaks one project rule, and for each one it is already recorded which guard should catch it.
The easiest way to show why this is needed is with a smoke detector. A detector with a dead battery is silent exactly like a working one in a house without smoke. Therefore, the detector has a "Test" button: pressing it should make it beep. A deliberate failure - such a button for each guard.
In the template demonstration, there are 42 deliberate failures. How to run it is described in the section "How to try the template". Here are three examples from the output:
caught The barrier looks in place but no longer refuses the-push-barrier-guards-the-declared-release-branch.test.js caught The check stopped seeing files and turned green because of it console-access-single-sink.test.js caught Two lines swapped: the send now runs before the record no-reminder-leaves-before-the-intent-is-recorded.test.js Violations: 42, caught: 42In each pair of lines, the top describes the failure, and the bottom shows the guard file that caught it; caught means "caught":
There is a guard, but it doesn't prohibit anything. The demonstration changed one response in the guard: instead of "no", it now responds "yes". It caught the guard that tries to send changes to the release branch and waits for a refusal.
The check no longer sees files and therefore turned green. The demonstration directed the check to an empty folder. It caught the minimal threshold.
Two lines have been swapped. The product now sends a reminder before recording the intent to send it. The guard caught "The reminder doesn't go away until it's recorded".
What to request from the agent in your project or for the expanded setup:
For each build check, break its rule in a project copy and show that the check failed. A check that didn't fail is considered absent.The agent introduces breaks into the project copy.
In the product itself, I rely on the guards because I can read the rule in each name, and on the browser run where the behavior is visible. I trust the other product tests on word: they are not checked for intentional breaks. Not all of the 89 guards are checked this way. The registry where each intentional break has a guard recorded that catches it, I have already made in the template.
4. Protection is tested by attempting to bypass it
Protection is a check that doesn't just warn about a violation but prevents the action from occurring.At the end of August, I separated development and release: each has their own branch. For the release branch, the most dangerous is a forced push. A regular push appends new commits to the GitHub history. A forced push rewrites it, and old commits disappear.
It was recorded in the specification that a forced push prohibits the rule in the GitHub repository settings. I asked the agent to check, and he found:
the rule can be created, and it appears enabled in the settings;
on my tariff for a private GitHub repository, it doesn't execute.
The tariff limitation is described in the GitHub documentation. On August 31, I removed this rule and recorded the reason in the project history.
Now the release branch is protected by a hook. A hook is a small program that Git runs on its own before a specific action. If the hook responds with "cannot," the action is canceled. My hook is executed before every push to GitHub and resides in the project folder, not in the site settings:
it rejects the push to the release branch;
it allows it only if the command explicitly includes confirmation that the push is intentional;
confirmation applies to a single command.
The hook can be bypassed using the command git push --no-verify, and the sender confirms the push themselves. These restrictions are written directly into the hook. If an agent accidentally repeats a previous command and forgets to change the branch, they will receive a denial. If they decide to bypass the protection, the hook won't interfere. For more details, see the section "What the guard does not do."
You don't need to read the hook code. The guard checks it: it attempts to push changes to the release branch without confirmation or with incorrect confirmation and fails if the push is successful.
Now I ask you to show the denial:
Demonstrate that the release branch protection is working: in a test copy of the project, try to push changes to the release branch without confirmation and output the full denial message.In your response, you should see the denial message itself, not the agent's explanation about the protection being in place.
5. The agent must communicate with you in the language of behavior
Until July 26, AGENTS.md did not specify how the agent should communicate with me in the chat.
([ModuleName], Difference in a hypothetical example. The question without this rule: "Move the sending processing to a background script?" The question with the rule: "Now, if the tab is closed during sending, the sending is interrupted. Make it finish completely?" I cannot answer the first question. I answer the second immediately, because it's a question about the product. Earlier, the agent could read the code and convincingly explain that everything was working. It became insufficient. Since August 22nd, he has his own Chrome: let him open the extension, click the buttons, and see. If it didn't reach the browser, it should be explicitly stated in the report: the output was made according to the code. He connects to the browser through Chrome DevTools MCP - a tool that allows the agent to control the browser: open pages, click buttons, read the console. With the full run, I've been dragging it out longer. A full run, or end-to-end test, is a run through the product from beginning to end, as a user would do. Until September 7th, it had only a line in the list of pending tasks and a dummy command that was intentionally failing.
Now this is a protocol - a step-by-step description of the check: minimum 70 scenarios; 40 page samples that depict external services and are located within the project itself; the agent goes through everything on its own in real Chrome. Before the 1.0.1 release, the run took about two hours: 69 scenarios passed normally, 1 deviation. The agent ran the scenarios without me. My part is to read the report and decide what to do with the deviation. With almost full storage, 17,674 templates, a modified template appeared in another extension window after 1.8 seconds, while the normal one was one. On October 12, I decided to release: the measurement was conducted on a very weak laptop, and its numbers couldn't be transferred to user machines. In the release report, this remained a deviation referencing my decision. The protocol (end-to-end test) is also checked: if a scenario doesn't have a page sample or the rule it checks, the test fails. In the template, there is a reduced version of such a run. The test process sends a reminder, and four page samples depict four possible outcomes. Here is what the agent sees in the console on the page where the service accepted the request, but the reminder did not appear: [Dispatch] - part of the program that writes to the log, here the dispatch. In the second set of brackets - the step in the process.
The story unfolds step by step: It is recorded that the reminder is being sent. Sending has started. The provider accepted the request. Proving that the reminder was received was not possible. The final status here is "not confirmed." The product doesn't say it was sent because it can't prove it. Almost every product has an action that can't be undone: money withdrawal, email, deletion. For me, it's sending a prompt to a foreign chat. Such a process can't be left only in code: it needs to be checked, but I can't check the code. The second reason I saw through my own experience. Every change the agent made in the main process of expansion, sending the prompt, broke what had been working well before. That means the agent didn't see the process as a whole: they modified one part without knowing what depended on it in others. The diagram shows him the entire process at once, not just the part he's modifying. Since June, the sending is described by a strict process diagram: 15 states and 69 transitions. State - where the process is currently, for example "it is recorded that the reminder is being sent." Transition - a step from one state to another. In essence, this is a regular process diagram.
The difference is that part of the schema agreement with the code is held by the machine: each line of the log starts with the name of the transition, exactly as in the schema; the build verifies names: every transition in the schema is present in the code, and the code does not have names that are not in the schema; the description of the process for people is created by the build itself from the schema. Therefore, each line of the log from a broken run can be found in the schema by name, and the agent does not have to guess what happened. The order in which the code goes through steps is not checked by the name verification: if you swap two lines of the log in the code, it will remain green. The order that is costly to violate holds a separate watchdog, which is discussed a bit below. This is how a piece of the test schema from the template looks: There are no storage locations where the record would survive a restart: on the sample page, the restart is depicted by a record made in advance. This checks that the product does not send the already recorded data again, not that the record will be saved. The build of the template checks the schema according to one rule: a step that cannot be undone starts only from a state that survives a restart.
Otherwise, the program will restart, not realize that it has already sent, and resend it. Place such a step in the scheme before the recording, and the build will fail. Place it before the recording in the code, and the watchdog "the reminder doesn't disappear until it's recorded that it's going to be sent" (Lesson 3, third breakdown) will fail. There are seven end statuses for sending. Among them is "Sent, not confirmed - check the chat", that is, "Sent, not confirmed, check the chat". From the agent, I also require indicating in the report that they were unable to check. What to request from the agent in your project: In the table, you can notice a missing case, even if you don't read the code. Skill (skill) - this is a file with instructions for the agent on one repeated action: which steps to perform, what to check, when to stop. Claude Code and Codex understand one format: a folder with a SKILL.md file. Usually, the agent itself decides when to load the skill based on its description. The skill can also be called by name: in Claude Code, you write /commit in the chat, in Codex - $commit, and all steps are performed by the agent. In February, I introduced the first two skills: commit records the work in the history, push sends it to GitHub. Then it was for convenience. On August 31st, an error was found in the commit-making skills: the skill itself set the commit author, while the committer (the one who made the commit) was taken from the computer's settings. They could mismatch. The error was fixed in all four commit-related skills.
The author's name and email are now declared in one place in the project, and the guard fails if the author names himself again. Until October 4th, I ran the review myself. I used a separate prompt to bring up the reviewer in a new context, and manually passed the report to the agent who wrote the code, with the task to evaluate which of the proposed changes should be implemented. Since October 4th, this has become a mandatory step in the process: before submission, each diff is reviewed by a reviewer who did not write it, and the author himself analyzes the findings. This allows us to find errors for which there is no guard yet. I submitted the completed template for review to Codex, who did not write it. He read the files and found 16 problems, although the build and 61 tests were green at that time. After the fixes, the guard sequentially breaks each build step in the project copy and requires the build to fail. The machine cannot verify that the review actually took place. In the template description, the wrapper is split into 15 layers, each with specified ways to check compliance with its rules. For three of the automatic check layers, there are no checks, only the text of the rules: the agent asks questions in the language of behavior; each diff is reviewed by an independent reviewer; the agent does not send anything outside the computer without my permission. In addition, the machine checks only the result. It does not know whether the agent read the specification before working. Other websites. The sample pages are in my project. They themselves do not change.
The real chat may have rewritten the input field or the send button during this time. The checks on the samples pass, but the extension no longer works for the user. Exactly this happened on November 1st. At that time, I fixed the settings file that the extension downloads itself, and managed without a new version in the store. Code quality. I can see the behavior and what the checks catch. I can't evaluate the code quality inside. Security and product setup. The template search for secrets in the commit. It doesn't search for vulnerabilities - holes through which the product can be hacked. It also doesn't evaluate the product setup as a whole. Intentional disabling of checks. An agent may weaken the check if it decides to do so. AGENTS.md prohibits this, and many such changes catch intentional breakages, but not all. The wrapper protects against agent errors, not against its decision to bypass the protection. An agent may rewrite the guards. A guard protects a rule, for example, "reminders are sent no more than once per hour". If an agent replaces "hour" with "day", the guard will turn green again: now it protects a different rule. No check will notice this; you can notice it only yourself. Therefore, the report has a section called "Changed guards" (in the template - Changed guards). The list of files comes from git, not from the agent's words. For each file, the agent writes which rule is now checked differently and why. If the agent didn't change any guards, the section says "none".
Read the report from this section before you check the results in the product yourself. Dangerous commands. Restrictions in agent settings catch random commands, not the agent's decision. They, for example, catch a forced push at the start of a command, but the same operation written differently or hidden in a script will be missed. Reading files is not prohibited: such a restriction does not hinder the agent with a command line. Therefore, secrets in the project folder cannot be kept. Solutions. What to build and why, I still decide. Step-by-step guide is in the template, here it is: https://github.com/yesgenius/agent-harness/blob/main/docs/GETTING-STARTED.md According to it, you can prepare a computer, run a demo of failures, and transfer the harness into your project. You will need a computer with Windows or macOS and a subscription to Claude or ChatGPT. The computer prepares the agent itself based on one prompt. English guide. To read it in Russian, right-click the GitHub page and select "Translate to Russian." If such an option is not available, open the Chrome address chrome://settings/languages and in the "Google Translate" section enable "Use Google Translate." The translator does not touch the prompts in the guide: they remain in English, so you should insert them as is. The agent will still speak to you in Russian: the prompts instruct it to respond in the language of your own messages, and until you write something, it uses the computer interface language. The harness holds what is recorded by the check.
What is recorded only in text, the agent still violates. Especially in a long session: the rules from AGENTS.md, which are 179 lines, get lost when the context is overwhelmed with work. I gradually came to six steps for working with an agent. On each step, I insert my own prompt, including repeating the rules from AGENTS.md. Below are the prompts I use. This costs about $60 a month: two Claude Pro subscriptions for Claude Code and one ChatGPT Plus for Codex. Tokens - units that measure the model's workload - I don't count them: these subscriptions are sufficient for me. I slice the work into slices. The first slice is a walking skeleton: the simplest version where all parts are already connected and working together, even if they know little or nothing :). Subsequent slices build upon it. I first discuss each slice with the agent at the xhigh effort level. This is a setting where the model thinks longer before responding. I discuss until the proposed solution satisfies me. I decide the product's behavior myself and in advance, adding examples or sketches. The model's design satisfies me: my product is a working tool. Issues were with others: buttons and switches behaved unpredictably. I resolved this with rules and tests. When the solution satisfies me, during the same session I ask to create a work order. The prompt is long and written for my project, so it's entirely under a spoiler.
The main thing is that: the work order is the complete and sole source of the task for the executor; facts about the current code are verified against the code; the solution is covered with tests; specifications are revised in the same work; the agent checks it himself in the browser, and I do manual checks only for what he couldn't verify; I make the commit. Prompt contains project specifications, adapt it to your case. docs/work-orders/ - work orders folder. Work order is stored in git to show what was assigned. For the executor during work, it's the only source of the task, hence the words in the prompt. How the product works now, is still described by specifications, while the work order describes what will change in them: everything it changes in the product, it also updates in them (point 6). Sometimes the work order contradicts the specification in some place, but doesn't mention that this place will change. Then the agent doesn't decide on its own what to believe; it stops and asks me. The agent's report on the work order is placed in docs/temp/, and it's not in git. AS-IS (in the prompt - ASIS) - how it's currently structured. Everything the work order says about the current code, the agent checks against the code, not from memory - this requirement prevents the agent from cutting corners and inventing things that don't actually exist. Red test (in the prompt - red-test) is written before fixing. It initially fails on an error, then passes after the fix.
So it's clear that the test catches exactly this error. Unit test checks one small part of the code separately from the rest. Principles: KISS - keep it simple; YAGNI - don't do it in advance; DRY - don't repeat the same thing twice; Fail Fast - stop immediately and loudly when there's an error, rather than continuing silently; Stdlib-only - without third-party libraries, where built-in tools are sufficient; Forward-Only - no backward compatibility: don't drag old things if they interfere; SRP - one module, one task; No Magic Values - every number and string in the code has a name. Name Hygiene. A long-lived name refers to behavior or a rule. Chat names, temporary documents, tasks, step numbers, and internal tags do not appear in code, tests, or specifications. After a month, such a word means nothing. Specification Drift - when the code does one thing, and the specification describes another. Everything I know about the new feature is born in step 1, during the discussion with the agent. Therefore, the same task that edits the code also edits the specifications, including the end-to-end testing protocol. After the task, I definitely read the specification diff (step 6).
Changes to specifications are a special control area, modified lines are always conveniently highlighted in the development environment. Chrome DevTools MCP - the agent checks it himself in the browser. Sample pages. If needed, the agent creates new pages on the project's test server, which behave like chats in the required situation. By hand I check only what the agent couldn't check in the browser. Commit - my decision. The work order writes the session in which a discussion took place: in it, the entire context of the solution is included. Another session will execute it, which hasn't seen this context. Therefore, the work order must be complete during the execution time: everything the executor needs to know about the task is written in it. The work order ends up being 1000-3000 lines long. At this point, the session context is full, and the agent starts to get confused. Therefore, first I extract everything that requires my decision from it: Then I read the work order myself. At first, I figure out what will change for the user, then I review it.
I ask the agent questions about the task. I don't read the entire task, and no one else does either. Therefore, an error in the technical part may well pass me by. I expect it to show up during checks, during product acceptance, or in the diff of specifications. If it doesn't show up, I'll miss it. I accept this risk. I ask twice: I tried sending the task to two agents in new sessions. Then I compared their comments with what the agent found in the current session. The current session turned out to be more useful. I don't have numbers, this is just my impression from work. Perhaps it helps that it still contains decisions from the discussion. A new agent has to collect all this context from the file. Code diff - that's a different matter: it is reviewed by a reviewer who didn't write the code (part 1, section 9). The words "independent reviewer" in the prompt are a role, not a fact: the same session that wrote the task reviews it again, meaning it's a recheck by the author. Before starting, the tree should be clean: everything that was done before the task should be committed. Then, after the task, the diff shows only its changes, and the drift of specifications is fully visible. I copy the prompt into a new session.
She starts with a clean context, and everything she needs to know is in the work order. The agent returns a ready command /goal: a link to the work order and a condition under which the work is considered complete. Without such a condition, the agent may stop halfway and write "done". With it, the agent works until one of three things happens: it produces a report where each item on the work order is confirmed by verification; it asks me a question without the answer to which it cannot proceed further, and stops; the allocated budget is exhausted. The work is only considered complete in the first case. The question and the exhausted budget stop the agent, but do not complete the work. In the last message, the agent writes why it stopped and what remains to be done. Who decides that the work is complete depends on the agent. In Claude Code, this is a separate model: after each move, it reads the chat, but does not open the files. In Codex, the condition is checked by the agent itself, which performed the work, meaning there is no third-party judge there, and this role is played by me (step 6). The command is the same for both agents, so the condition is designed for a more strict case: the report must be output directly into the chat, not just told that it is in a file. The goal text cannot be longer than 4000 characters, so all detailed information is in the work order, and the command only refers to it. An example of such a command is in the template, in the file docs/WORK-ORDER-TEMPLATE.md. There, the condition requires outputting the second section of the report - "Modified Guards", Changed guards (about it - in the section "What the wrapping does not do"). The agent wrote that everything is ready.
I already know what to ask next: what remains unfinished and what he hasn't checked. He himself somehow doesn't always start with this. Therefore, even after a good report, I send him these prompts: Then I read the diff specifications - this is a mandatory step. I don't read the code, but through the diff specifications, it's clear that the order changed the product description. If something is wrong or unclear there, I return to the agent with questions. Then I perform manual checks from the report: what to open, what to do, how it should look. If the result isn't correct, I send the logs to the agent along with a screenshot. When everything is accepted, I write to the agent "make a commit". The schema will start stopping incorrect steps on its own. Currently, the schema for sending is a description. The build checks that the names of steps in the code and in the schema match, but does not check the order in which the code processes these steps (lesson 7).
In the next project, the code won't be able to proceed to the next step on its own: it will ask one function, which will check against the schema. If such a transition isn't in the schema from the current state, the step won't execute, for example: sending won't start until it's recorded that it begins. The function also writes a log line, so the log and schema won't diverge. The schema will only have major steps. Minor actions within a step—open tab, insert text, click button—will remain as regular code: if you detail them in the schema, you can't read the schema as a process. Against: only incorrect step order is caught. Schema won't catch an error within a step: for example, when two actions happen simultaneously and interfere with each other or another page behaves differently than expected. But in the product's history, there are such corrections for sending. The product doesn't have this function, so I haven't seen its benefits yet. Each watchdog will receive an intentional break, and the tests for the expensive process—too. In the product, I trust the other tests on word (lesson 3). In the template, the registry of breaks already exists, but a watchdog without a break is allowed: a dash is simply placed in its line. In the next project, the check will fail on a watchdog without a break. The exception is one, and it's recorded: a watchdog that checks breaks itself. Breaks will also be received by the tests for the expensive process: transition not from the correct state, irreversible step before recording. I want to test each rule I rely on during acceptance by attempting to break them.
Against: each defect is a copy of the project and an extra guard run, so tests take longer; other product tests will remain just words. Acceptance will become part of the report, not a separate prompt. Unresolved defects, incidental defects found, and uncompleted checks will become mandatory sections of the report, an empty section - the word "no". The "Changed guards" section in the template is already structured this way. Against: the /goal condition checks that the section exists, but not that it's actually correct; and a separate question after "done" forces the agent to review what was done. Prompts will become skills, and the rules from them will be guards. I manually insert six prompts into each slice, and half of the prompt template repeats AGENTS.md. A rule written twice will eventually diverge from its copy. Against: the guard catches a violation after work, while the rule in the prompt warns in advance, and this is cheaper. AGENTS.md will become shorter, and the rules will be closer to the step where they are needed. In the project, this file takes 179 lines, while the template has 130. A rule needed on one step will move to the skill of that step, and what remains in AGENTS.md will be what is needed in any task. Against: the reason for the rule is only explained in AGENTS.md, while the skill provides the rule itself. Without knowing the reason, the agent will violate the rule in a case the skill doesn't mention. What do you consider self-deception or redundant in the provided workflow diagram? If you are not reading the code that the agent writes, what exactly are you taking when you say "taken"? Models become smarter, and some elements of the wrapper can be removed. How do you determine what can be removed? Template: https://github.com/yesgenius/agent-harness Extension on which all of this grew: https://chromewebstore.google.com/detail/pcpciffaliaooacnhiefjiegigjidehp6. The agent should see what was done
7. The most expensive process is described by a diagram:
8. Repeated action becomes a skill
9. The author does not check himself.
What the wrapper does not do
How to try the template
Part 2. How I work with the harness now
Step 1. Discuss the next slice
Step 2. The agent writes a work order
Step 3. Extracting questions about the product
Step 4. Task review
Step 5. Execution in a new session
Write a prompt for the agent-coder to perform the task with the /goal command.
Return in a copyable format.
Step 6. Acceptance
Part 3. What I will change in the next project
Part 4.
Questions

