# My coding agent found a bug, then hit it again in 102 imports

> Source: <https://archdocs.io/blog/how-we-use-design-docs-with-coding-agents>
> Published: 2026-11-01 00:00:00+00:00

# My coding agent found a bug, then hit it again in 102 imports

My agent hit an editor bug while drafting a design doc, worked around it and kept a note on my machine. An hour later the same bug failed 102 of 127 imports. This is how the design doc's Work Log turned that into a record the next change can find.

- Author
- Aylon, founder of ArchDocs
- Published
- Reading
- 20 min read

On November 1 my coding agent hit an error while drafting one of our design docs. The editor refused its markdown with `Invalid collection of marks for node text: bold,code`, because a piece of inline code sat inside bold text. The agent told me the write had failed "because I nested code inside bold text", removed the bold, sent the spec again and carried on. A few minutes later it saved a note about the rejection to a memory file on my machine, calling it a product bug worth fixing in the editor.

About an hour later, the same agent ran the feature it was building against 127 of our own design documents. 102 of the 127 imports failed with the same error.

The session record shows the sequence, not a decision to drop the bug. The agent was writing the spec at the time, nothing had been built, and the design doc's Work Log had no entries yet; the first one came twenty minutes later. Its message to me treated the rejection as a mistake in its own input, so it fixed its input. The only place the bug was written down was a note on one machine that nothing would show to whoever planned the next piece of work. It wasn't the first time either: earlier that morning, a session writing a different design doc hit the same error and rewrote around it the same way.

The second time, the problem landed somewhere other people could see it. Within fifteen minutes the design doc's Work Log held the blocker, the fix, a note that the fix was outside the agreed plan, and a lesson proposed for whoever touches that editor code next.

I'm Aylon, and I build ArchDocs. Most of the implementation is done by coding agents, so we built the product around the idea that a design doc should hold the intent, decisions, implementation history and outcome of a change, and hand all of it to whoever works on that part of the system next. We use it on our own changes. What follows is one of them, start to finish, with screenshots of the record as it stands.

## [One record per change](#one-record-per-change)

A design doc in ArchDocs has a few parts that do different jobs. The spec says what problem we're solving and what was decided. The implementation plan says how, which parts of the system it expects to touch, and how each step will be checked. The Work Log records what actually happened while the work was underway. The evidence says what shipped, what supports that, where it differed from the plan and what was left undone.

The split pays off once work starts. The spec and plan record what was agreed, and shipping freezes them; later edits need an amendment with a reason. Everything that happened after agreement goes into the Work Log and the evidence, so the original design and the actual history sit side by side instead of the second overwriting the first.

None of this is for every change. The skills tell our agents to propose a design doc only when a change crosses a boundary between components, needs someone else's sign-off, will take more than one pull request or session, or adds a dependency, a data store or new personal data, and to say nothing about design docs for a change inside one component, a dependency bump, or a copy or config edit.

## [The change, and the decisions I made](#the-change-and-the-decisions-i-made)

DD-0022 added a way to import design docs, RFCs and ADRs that teams already have in other tools. The spec's problem statement was specific: until then, every document arrived one at a time as a fresh draft, with no trace of its original author, date or identifier, and running an import twice made two copies. A team that adopted ArchDocs started with an empty history, so search and task context had nothing to work with until people wrote new documents. Our own repository had 110 specs and 176 implementation plans waiting.

The agent drafted the spec. Where it reached a decision it wasn't entitled to make, it raised a tracked question on the doc with options and a preferred answer instead of picking one. DD-0022 had four. Q1 asked whether an agent may create imported documents directly as Shipped, which bends our own rule that a person decides when a design doc has shipped. I allowed it for historical imports through one separately authorized code path. Q4 went differently.

Most RFCs mix the design and the rollout plan in one page, and the agent asked whether an imported page should land whole or be split into a spec and a plan by AI. It preferred landing whole: predictable, and it works with AI turned off. I said it should be a choice the person importing makes. Version 3 of the spec turned that into the design: an import-level setting, "Keep each document whole" or "Split into spec and plan", with a per-row override, offered only when AI is on, and marked "(decided in Q4)". Both of the agent's original options went into the rejected alternatives, and anyone who later wonders why the import dialog has a split setting can read who decided and why.

DD-0022 had no formal approval step. Our organization doesn't require one for a change this size, and the four answered questions were the sign-off. Organizations that want a formal approval step can require one on Business.

## [What the agent keeps up, and what stays yours](#what-the-agent-keeps-up-and-what-stays-yours)

Keeping a record like this by hand would mean narrating every commit, test run and surprise to a document while also doing the work. That's the part I hand to the agent. In my setup the agent is Claude Code with the [ArchDocs plugin](https://github.com/archdocsio/archdocs-plugin), connected to ArchDocs over [MCP](https://archdocs.io/docs/mcp/claude-code). The plugin's skills tell the agent when a change deserves a design doc and how to write one, what to record while it works, and how to close out. The MCP server gives it the tools and enforces the rules that shouldn't depend on an agent's good behavior.

Here is how the work divides at each stage of a change:

1. Before the work, the agent drafts the spec and plan, raises open decisions as questions and fetches related context. ArchDocs refuses an agent's write that has no summary. You answer the questions that set policy.
2. During the work, the agent logs commits, exact test results, deviations, findings and a handoff when it stops. ArchDocs checks commit references against GitHub when it's connected. You read the log when you want to know where things stand.
3. At the end, the agent writes the evidence, including what wasn't done. ArchDocs computes acceptance criteria if you configured them and records who decided the change shipped. You decide whether it shipped.
4. When the next change starts, the agent asks for task context before planning. ArchDocs returns related records, each labelled with how it was found and how far to trust it. You accept or drop the constraints the agent proposed.

The skills, and the plugin's hooks, guide the agent's side of this. The hooks notice a commit, a test run or a finished subagent and remind the agent when the Work Log is behind; they never write to ArchDocs themselves, and a reminder doesn't guarantee the agent records everything. DD-0022's log predates them, so every entry in it came from the agent following the skills.

The decisions reserved for people are enforced by the server, not by the skills. An agent can't approve a variation, accept or reject evidence, authorize acceptance criteria, attest for a person or ship with an exception on its own. ArchDocs refuses those calls unless the agent passes a statement it says a person made in that session, then records the decision in that person's name, under their permissions, with the client it came through, labelled relayed. ArchDocs can't tell whether the person really said it, so on Team and above an organization can require each kind of decision to be confirmed by the person (through a prompt in their agent, a link or Slack) or made only inside ArchDocs. Settings, the verification policy and variation types change only in the app.

Shipping depends on the organization's verification policy. Once a design doc has authorized acceptance criteria, the default policy refuses an agent that tries to ship it without a person's decision. Without criteria, ArchDocs lets an agent mark the doc shipped on its own. The skills tell it to wait until a person says the work shipped, but that's guidance the agent follows, not a rule the server enforces.

DD-0022's plan named the three parts of our system it expected to change (the API, the frontend and the API contract), broke the work into twelve tasks, and gave each task its check. Its risks section held things we'd learned the hard way, such as releasing the plugin only after the API deploys, because the skill calls a tool that doesn't exist in production until then. None of that is in the code, so a new session would otherwise find it out by breaking something.

## [The plan missed something](#the-plan-missed-something)

Task 6 tested the agent path against real input: our own `docs/superpowers/` folder, 286 files mapped to 127 documents, imported into a local organization over the real MCP tool. 25 imports succeeded and 102 failed.

Our design doc editor is built on Tiptap, whose inline code mark excludes every other mark by default. Markdown such as ``**` createdAt`**`` failed the editor's schema check, and the whole document was rejected. Built as the plan described, the import refused four of every five real documents.

Nine minutes later the agent logged the fix.

The fix also changed behavior outside import: the editor and the agent's own document writes stopped rejecting bold or italic code, which is ordinary GitHub-flavoured markdown. It turned out to be incomplete. The editor ignored the override the fix relied on, so those writes went through with the bold or italic around the code silently dropped. A follow-up commit that night, eb7c428a, extends the editor's code mark itself so the outer marks survive, and adds tests that check them. The [full entry](https://archdocs.io/blog/how-we-use-design-docs-with-coding-agents/04-worklog-e6-full.png) shows the constraint captured from the first fix.

Four minutes after the fix, the agent captured the finding as a constraint attached to the files it governs: any change to the editor's mark set must keep inline code combinable with bold, italic and links, and keep the round-trip test for those cases green. A capture from the Work Log stays proposed until a person accepts it, and ArchDocs labels it "From a Work Log finding, not an approved rule" so nobody mistakes it for policy.

Each piece does a different job. The code fix and its tests address the defect. The Work Log keeps the finding, the deviation from the plan and the record around them. Task context, covered below, is what makes the recorded constraint show up when someone works on those files again.

Two smaller surprises followed the same path. Two files contained a NUL character that Postgres refuses to store, which got its own fix, and the third run imported all 127. The Notion source tried to attach images to documents that were already shipped and frozen, so image handling moved inside the import. Both went into the evidence's list of deviations.

## [A log the next person can use](#a-log-the-next-person-can-use)

DD-0022's Work Log ended the build with eighteen entries. They're checkpoints: each commit, exact test counts rather than "tests pass", what a delegated run produced and what the review of it found, and each departure from the plan the agent noticed. The implementation ran through a second agent, with Codex writing code from a work order and Claude reviewing each result, running the checks and keeping the record. Claude kept the record because it was the session reviewing Codex's output.

Two entries record things a reader would otherwise dig out of the code. E-2 ends with a paragraph headed "Calls I made that the plan left open", listing four small product decisions the agent made because the plan didn't, so a person can review and reverse them instead of discovering them in the code months later. E-13 records three failing tests in an older suite that had nothing to do with this change, "so the next person does not mistake them for an import regression."

The log holds what the agent decides to record, and capture is a choice too. A second lesson that day, that our marketing site has tests pinning the docs pages and the number of MCP tools, stayed in a Work Log entry and was never captured as a constraint.

When the agent stopped, it left a handoff.

I used that handoff myself. When I came back to DD-0022 to write this post and correct its record, my agent's first call was `get_journal_handoff`. It returned E-17, marked it stale because a later entry (E-18, recording the ship) had been added after it, and reported no open questions.

## [The evidence](#the-evidence)

The evidence is where the record says what shipped. DD-0022's has four sections: outcome, verification, deviations and not done.

DD-0022 used recorded test and CI evidence, without configured acceptance criteria, so ArchDocs computed nothing on its own; the header says so. Because those results are the agent's report, I checked them myself with the GitHub CLI. Run 41310251591 on the final commit succeeded: build, unit tests, integration tests, the Docker image and both deploys. Its end-to-end job was skipped, so the "5 of 5" Playwright import suite is a local run the agent reported, not a CI result. The run before it, 41309759807, failed on two marketing tests the agent's local checks hadn't covered, which the Work Log records along with the fix. Both runs are in our private repository, so I can't link them here.

When a change needs more than a report, you can configure [acceptance criteria](https://archdocs.io/docs/design-docs/acceptance-criteria): statements a person authorizes, satisfied by attestations or, on Business with linked pull requests, by facts ArchDocs reads from GitHub. ArchDocs computes each result, and an agent's attestation counts only where the policy allows one.

The ship itself was my decision. I told the agent "Ship it and then tell me how I can try out the import on a few docs." It marked DD-0022 shipped with that sentence attached, and the header shows it as relayed through Claude Code. Under our policy the statement wasn't required: DD-0022 had no acceptance criteria, so ArchDocs would have accepted the ship from the agent alone. The agent waited because the skills tell it to ship only after a person says the work shipped, and passing my words along is what put my name and the relayed label on the record.

Checking the record for this post turned up one mistake. Every commit the agent logged named the repository `archdocsio/archdocs`; ours is `archdocsio/monorepo`. ArchDocs had been checking each reference against GitHub and showing "Not found" next to all of them, and the same wrong name sat on the captured constraint's file paths. Entries and captured file paths can't be edited, so we corrected the record by adding Correction entries and a corrected constraint marked as superseding the original. The original entries are untouched and now say "Corrected by", the corrected references resolve on GitHub, and the supersession takes effect only when a person accepts the new constraint. The [correction entry](https://archdocs.io/blog/how-we-use-design-docs-with-coding-agents/05-worklog-e19-correction.png) shows both.

## [The next change starts with what we learned](#the-next-change-starts-with-what-we-learned)

Suppose the next change to the editor adds a strikethrough mark. It will touch `packages/doc-editor/src/extensions.ts`, the same file as the editor fix, which is where the code mark is extended to combine with bold, italic and links. A change that reorganizes the editor's extensions while adding a new mark could drop that and bring back the exclusion that made 102 of 127 imports fail, and it would also start rejecting the agent's own document writes again. What the next agent needs to know is short: keep the code mark combinable with other marks, keep the round-trip test for bold, italic and linked code green, and test with markdown like ``**` createdAt`**``, because imported documents and agent-written docs often contain it.

When the agent follows the skills, nobody has to point it at DD-0022. Before planning, the skills have it ask for [task context](https://archdocs.io/docs/design-docs/task-context) with a description of the change and the files it will edit. ArchDocs returns the decisions, constraints, open questions and design docs recorded against those files, with the same labels.

We ran that query after the correction, against the real repository and the two files a strikethrough change would touch. This is a demonstration. No such change has been made.

Before the correction, the same query couldn't match the files and found the constraint third, through text search. Now it's the first result, found by path. The query used no catalog objects; the file paths recorded on the constraint were enough, and catalog objects, when you have them, give the query another way to match. The [full result](https://archdocs.io/blog/how-we-use-design-docs-with-coding-agents/08-task-context-full.png) also lists the original capture, labelled as having a newer item that proposes to replace it.

A person reviewing that future change gets the same context and can check the proposed constraint against the implementation before accepting or rejecting it.

## [Try it on your next meaningful change](#try-it-on-your-next-meaningful-change)

Pick one change in your system that crosses a boundary, needs a sign-off or will outlive one session, and run it through ArchDocs:

1. Describe it to your agent and let it draft the spec and plan. Answer the questions it raises, especially the ones that set policy, and feel free to pick an answer that isn't on the list.
2. While it works, open the Work Log now and then. Look for deviations, the calls it made that the plan left open, and the handoff when it stops.
3. At the end, read the evidence. Check what was verified and what was only reported, read what wasn't done, and decide whether it shipped.
4. When related work begins, have the agent ask for task context before it plans, and accept or drop the constraints it proposed last time.

[Create a free ArchDocs account](https://app.archdocs.io/register), then add the plugin in Claude Code:

```
/plugin marketplace add archdocsio/archdocs-plugin
/plugin install archdocs@archdocs
```

Run `/mcp` and sign in to the `archdocs` server with the same account. Then run `/archdocs:design-doc` with a sentence about the change you want to make. The [Claude Code setup guide](https://archdocs.io/docs/mcp/claude-code) shows how to check that the plugin and the connection are working.

What you can try depends on your plan, and none of it needs an early-access request. Free includes one design doc with the spec, plan, questions, Work Log, evidence and up to ten acceptance criteria, which covers steps 1 to 3, and the agent can capture constraints along the way. Retrieving them with task context (step 4) needs Team, which also adds unlimited design docs and importing the ones you already have. Formal approvals, linked pull requests and criteria checked against GitHub are on Business.

**Aylon, founder of ArchDocs** 20 min readUpdated

More in Architecture as code

Start
