Chapter 7 of 7 · 9 min read
Six skills compete for the requests one skill used to win
On this page
engineering-standards is 903 lines of markdown, about 11,400 tokens, and it fired 214 times last month. Its table of contents lists migrations, API design, testing conventions, the release process, on-call etiquette, and the code-review checklist. The on-call section — 74 lines about acknowledgement windows, handover notes, and when it is acceptable to page someone at home — was relevant to 9 of those 214 runs and was in context for all 214.
The reason anyone started looking at it was an audit of migration runs. Across 60 requests that added a column, the rollback file existed before the change was proposed in 43 of them. That is a 72% compliance rate on a rule the document states plainly, and the question the audit could not answer was why the other 17 failed. The rule was present in every one of those runs, so it was not a routing miss. Whether it was buried at line 611, or crowded out by 800 lines of unrelated material, or quietly outranked by the release section's advice to prefer the smallest possible change set, is not a question the transcripts can settle, because every rule the team owns was loaded on every run.
The argument for one file is better than it gets credit for
The team defending the monolith — one skill file carrying every standard the team owns, loaded whole whenever any part of it is wanted — is not being lazy, and the strongest version of their case is worth stating properly because parts of it survive the split.
One skill has one description, so there is exactly one routing decision to get right and no boundary disputes at all — the entire subject of the previous chapter simply does not arise, because nothing can contradict a document it is inside of. Contributors have one file to find and one review path, and a rule that touches two subjects, like the rule that a migration deploy needs a release note, is written once instead of being duplicated into two skills where the copies will diverge. The description can be broad without much penalty, because when the skill covers everything, a false positive costs tokens rather than wrong behaviour. And there is a real completeness argument: once it loads, everything the agent might need is there, so the agent never gets half the standard.
That last claim is where the case starts to leak, because "everything is there" and "everything is applied" are different properties, and the 72% number is the gap between them. But the maintenance argument is genuinely correct, and a split that ignores it produces six files that drift apart within a quarter.
Two failures the monolith produces and six skills do not
The first is attribution. When every rule loads on every run, a violated rule cannot be distinguished from an absent one, a crowded-out one, or one that lost to a neighbouring instruction. There is no experiment available either: changing the migration section to see whether compliance improves changes the context of all 214 runs, including the 154 that had nothing to do with the database, so any measurement is confounded by everything else in the file. With a 140-line db-migrations skill, the same edit is an intervention on a population you can define — the runs where that skill loaded — and the before-and-after is readable. After the split, that same rollback rule ran at 94% on the next 60 labelled requests, and the 4 remaining failures were all the same shape, a request phrased as a code review of an existing migration rather than as writing one, which is a routing problem with a name.
The second is behavioural interference, which is the more uncomfortable one because it means the monolith is not merely wasteful. 11,400 tokens of standing procedure in context changes what the agent does with the request in front of it. The clearest instance from these traces: the on-call section says that during an active page you should apply the smallest change that stops the bleeding and defer cleanup to a follow-up ticket. That is good advice about incidents, and in 6 of the 17 rollback failures the request mentioned production being slow, the agent read the situation as incident-adjacent, and the smallest-change instruction was the visible reason a rollback file got deferred. A skill that only covers migrations has nothing to say about incidents, so it cannot leak advice into them.
There is a third cost that is about people rather than models. A file everyone owns is reviewed by whoever happens to be free, and the API-design section acquiring a sentence about backwards compatibility is not something the data team will notice in a 903-line diff. Splitting puts each document in front of the people who care when it changes, which is the ownership argument from the first chapter applied inside a skill directory rather than between a skill and a tool.
Not every section is a skill
Before deciding how many files come out, each section is worth testing against what a skill actually is, because a table of contents is a poor guide to a set of skills. Some of these sections are procedure the model applies, which is the shape that belongs in a skill. Others are not.
| Section | Lines | Runs it mattered in | What it actually is |
|---|---|---|---|
| Migrations | 210 | 60 | A skill. Clear task, clear triggering vocabulary. |
| API design | 168 | 44 | A skill, with a messy boundary against code review. |
| Testing conventions | 145 | 51 | A skill, though half of it duplicates the linter. |
| Release process | 132 | 23 | Mostly a tool. Approvals and freeze windows are policy; the release itself is deploy. |
| On-call etiquette | 74 | 9 | Not a skill. Human process the agent does not execute. |
| Code-review checklist | 174 | 66 | A skill, and the one every other request also matches. |
Two rows change the plan. On-call etiquette leaves the skill directory altogether and goes back to the team handbook, because nothing in it is a procedure the agent carries out; keeping it as a seventh skill would preserve 74 lines of context cost for a document the agent has no use for. And the release section is the seam from the first chapter showing up mid-refactor: the approval matrix is skill material, the freeze-window check should be a refusal in the deploy tool where it can actually hold, and what remains is small enough to fold into the deployment skill rather than standing alone.
What gets harder the day the split lands
Six descriptions now compete for requests that one description used to win by default, and the boundaries are not clean. "Review this PR — it adds a /v2/invoices endpoint, a migration and tests" matches four of them honestly. "Should this field be nullable" is a migration question and an API-design question. "Why is this test flaky" is testing conventions until you notice the flakiness is a transaction-isolation problem in a fixture, which is migrations.
The failure that follows is predictable and gets misdiagnosed. In the first week after a split, some requests match nothing, some match two skills that disagree, and the team blames the split rather than the descriptions — which is a shame, because the requests that now match nothing were already being answered badly by a monolith that loaded and then buried the relevant 12 lines. Without a baseline, that is unarguable in either direction.
So the thing to land before the split is the labelled request set from the second chapter, extended across all six areas and measured against the monolith first. A hundred to a hundred and fifty real first-messages, pulled from transcripts rather than invented, each labelled with which of the six areas should govern it and — for the ones that legitimately span two — which one wins and why. Labelling those spanning cases is where the boundary decisions actually get made, and making them against real requests is considerably easier than making them in the abstract, because a concrete request usually has an obvious primary intent even when its subject matter is mixed.
| Monolith (baseline) | Six skills, week 1 | Six skills, after description fixes | |
|---|---|---|---|
| Requests where the right material loaded | 138 / 142 | 119 / 142 | 136 / 142 |
| Requests where the right material was applied | 96 / 142 | 112 / 142 | 129 / 142 |
| Median tokens loaded per run | 11,400 | 2,150 | 2,310 |
| Runs loading 2+ skills | 0 | 37 | 29 |
| Attributable failures | 0 of 46 | 30 of 30 | 13 of 13 |
The first row is the one that gets people nervous, and it is a real regression that was fixed by rewriting three descriptions using the near-miss method rather than by reversing the split. The second row is what the exercise was for. The last row is the durable win: after the split, every failure names a document, which means every failure has an owner and a possible fix.
The rest of the pre-split checklist is short and comes from the earlier chapters. Each new skill gets an expected-behaviour block, written by somebody who did not author the skill. Each pair with a real boundary — migrations and code review, API design and code review — gets scope lines on both sides, and the precedence file records the tiebreak. The monolith stays in the repository, unregistered, for a month, because reverting is otherwise a reconstruction rather than a commit.
skills/
├── PRECEDENCE.md
├── db-migrations/ # 210 → 140 lines after dropping duplicated linter rules
│ ├── SKILL.md
│ ├── EXPECTED.md
│ ├── reference/column-types.md
│ └── scripts/check_backfill.py
├── api-design/SKILL.md
├── testing-conventions/SKILL.md
├── code-review/SKILL.md
├── deployments/SKILL.md # approvals; freeze window now enforced in the deploy tool
└── _archive/engineering-standards.md # unregistered, delete after 2026-09-15Six was not a target. It is what came out of asking, section by section, whether the material was procedure the agent applies and whether real requests distinguish it from its neighbours. On another team the same 903 lines might cut into four.
Where this is still unsatisfying
Nothing here scales indefinitely. At six skills the descriptions can be hand-tuned against a labelled set; at forty, which is what a large organisation's directory looks like within a year, the descriptions are competing in a space no one person has read, and the labelled set that keeps them honest is itself a maintained artefact with an owner. Approaches to that — routing indexes over skill descriptions, retrieval rather than direct matching, skills that reference other skills as sub-procedures — exist and are moving quickly, and none of them removes the need to know what a correct load looks like on requests you have actually seen.
The other unsolved piece is that everything in this topic measures the wrong thing slightly. Load rates and compliance rates are proxies for whether the agent did the work well, and a skill can score perfectly on both while making the output worse, because the procedure it encodes was a bad procedure. No amount of routing discipline detects that. It is caught by the same thing that catches it in code: somebody who knows the domain reading the results and saying that is not how we do it.
Which is the argument for writing one soon rather than planning a directory. Take a task your agent already does adequately, write forty lines of procedure that would make it better, describe it in the vocabulary of the requests that should trigger it, ship it, and read the next twenty traces where it fired. The gap between what you expected and what the transcript shows is where the rest of this gets learned, and it arrives faster than any amount of design.
Agent skills — read the current version at https://daviddominguez.dev/learn/en/agent-skills/six-skills-compete-for-the-requests-one-skill-used-to-win