# Make this repository AI-native
You are working in a repository you did not write. Your job is to leave behind a
small system that lets an AI agent do useful work here without drifting.
## What done looks like
When you finish, this repository has five things, and not one of them contains a
claim that nothing checks:
1. **Standing instructions.** One short file an agent reads before every task,
holding only what it cannot infer from the code.
2. **Domain rules.** Deeper files, one per area, each declaring the paths it
governs so it loads when that area is touched and not otherwise.
3. **A decision ledger.** Append-only, dated, never rewritten. Why things are the
way they are.
4. **Guardrails.** Automatic checks for the invariants that actually cost
something, each one proven by breaking it on purpose.
5. **A loop.** Written down, so the next defect becomes a mechanism rather than
another paragraph.
If some of these already exist, audit and repair them. If none do, build them.
Either way the governing idea is the same: an instruction nobody checks will go
stale, and a stale instruction is worse than a missing one, because an agent
follows it without hesitating. Every claim you write must either be verifiable
against the code today, or be replaced by a mechanism that verifies itself.
Prefer the mechanism.
## Absolute constraints
- Never run git commit, git push, git reset --hard, or any history rewrite.
- Never run migrations, deploys, or any command that touches a live environment.
If a command's blast radius is unclear, do not run it. Ask.
- Never delete or overwrite an existing file without showing the diff and asking.
- Do not install dependencies without asking.
- Report what you could not verify. An unverified claim stated as fact is the
exact failure this system exists to prevent.
## Phase 1: audit. Change nothing.
Read only. Produce a written report, then stop and wait.
**1a. What already exists.** Look for agent instruction files at the repo root
and in any tool config directory, plus README, CONTRIBUTING, ARCHITECTURE, docs,
and ADR directories. For each: path, line count, rough token cost (words divided
by 0.75), last modified, and how much of it restates something the code already
says. If there is nothing, say so plainly and move on. That is a normal starting
point, not a failure.
Then check whatever exists for truth. Sample every concrete claim: does that file
exist, does that function have that name, does that command run, is that list
complete? Report how many you checked and how many were wrong. Do not soften it.
**1b. What conventions the code actually follows.** Do not ask anyone. Read.
The layering, the entry points, the error-handling shape, how modules are wired,
what gets validated where. Note where the pattern is consistent and where it has
forked into two dialects. A forked pattern is worth writing down. A consistent
one usually is not, because the code already teaches it.
**1c. What has already gone wrong.** The most valuable part, and the easiest to
skip. Evidence, not intuition:
- Commit messages shaped like incidents: fix, revert, hotfix, regression,
"again", "actually". A bug fixed twice is a guardrail waiting to be written.
- Defensive comments: "do not remove", "must run before", "looks redundant but".
Each is an invariant someone learned the hard way and could only write in prose.
- Clusters of TODO, FIXME, HACK. Where they cluster matters more than how many.
- Anything touching money, authentication, tenant or user isolation, data
deletion, external calls, retries, background jobs. Silent failure costs most here.
- The same defensive check repeated in many places. Repetition under duress is an
unmechanised invariant.
If the history is squashed or too short to be useful, say so and lean on the
other sources. Do not invent incidents to fill the list. A short evidenced list
is the correct output; a long speculative one is worse than none.
**1d. What verification exists.** Test framework and how it runs. Linter, and
whether it gates or merely reports. Type checking. CI: what actually blocks a
merge. Then the question that matters: of the invariants in 1c, which are caught
automatically today, and which depend on someone remembering?
**Stop here.** Report what exists, what is stale with counts, the invariants with
their evidence, and the gap between the two. Wait for a decision.
## Phase 2: propose
For each invariant from 1c, propose the cheapest mechanism that would catch a
violation. Cheapest first, because the cheapest one that works is the one that
survives:
1. A type or signature that makes the wrong thing fail to compile.
2. A test that derives what it expects from the codebase rather than from a list
you typed: it walks the tree, parses the config, reads the schema. This is the
one that does not go stale, because there is nothing to update.
3. A lint rule, custom if the linter supports authoring one.
4. An assertion at build or startup, so a misconfigured deploy fails before it
serves traffic.
5. A CI step or hook.
6. Prose. Last resort, for what genuinely cannot be mechanised.
Rules for the list:
- **One guardrail per thing that has actually broken.** If you cannot name the
incident, the commit, or the defensive comment behind it, do not propose it.
- **No hand-maintained list, ever.** If it needs someone to add a line when they
add a file, it is already broken. Derive it.
- Say what each will not catch. A guardrail whose limits are unwritten gets
trusted past them.
Present it. Wait for approval before building.
## Phase 3: build the guardrails, and break each one
Confirm the working tree is clean, or that every file you will touch is
unmodified. If not, stop and say so. This phase edits source and must not run
over uncommitted work.
One at a time:
1. Write it. Run it. Confirm it passes on the correct codebase.
2. **Break the invariant deliberately.** Copy the file to a temporary location
outside the repo first. Introduce the exact defect the guardrail exists to
catch. Run again. It must fail, and the message must name the file and say
what is wrong.
3. Restore from the copy, not from memory. Confirm byte-identical. Re-run, green.
4. Record what you broke, the failure output, and the restore.
Not optional, and not skippable for being obvious. A guardrail that has never
failed is decoration, and worse than nothing because it manufactures confidence.
Expect some of your first attempts to pass while broken. That is the most common
defect in this kind of work. If you cannot make one fail on purpose, delete it.
## Phase 4: write the instruction layer
Now write the standing instructions and the domain rules, with the guardrails in
place so the prose no longer has to carry what a check now covers.
**The standing instructions.** One file, as short as it can be while remaining
true everywhere. It holds: what an agent cannot infer from reading the code, what
is deliberately not obvious, what is dangerous, the commands to run, and a
pointer to where the domain rules live. Nothing else. Specifically it does not
hold a tour of the directory structure, an explanation of the framework, or any
list of files, modules or tables. Point at the directory instead.
**The domain rules.** For each area with rules of its own, one file, named for
the area. At the top, declare the paths it governs, in whatever form the local
tooling reads, so it loads when that area is touched and stays out of the way
otherwise. Inside: how this area works and why, the invariants that must hold,
the mistakes already made here, and what to re-run before calling a change done.
Do not restate anything another rules file owns.
If an instruction file already existed, this phase is mostly deletion: remove
everything the code, the filesystem, or a new guardrail now states, and move
whatever is area-specific out into its own file. Report the token cost before
and after. If it grew, justify it.
## Phase 5: the ledger and the loop
Create an append-only decision log, newest first. One entry per non-obvious
decision: date, what was decided, what was rejected, why. It records reasoning,
not instructions. The rules say what to do; the ledger says why that was chosen,
so the argument is not had again from a worse position.
Two properties keep it usable. An entry later overturned is marked in place with
one unmissable line pointing at what replaced it, so a reader going top-down
cannot implement a dead decision. And once it is too long to read whole, generate
an index of headings and line numbers from the log itself, with a check that
fails when the index is stale. Never hand-maintain that index.
Then write the loop into the standing instructions, as the closing section:
- A decision gets its ledger entry in the same change as the code, never after.
- When something breaks twice, build the check. Do not add a paragraph.
- When a check replaces a rule, delete the rule in the same change.
- These files must shrink as often as they grow. If they only grow, the loop is
not running.
## Final report
State plainly: which of the five parts existed before and which you created; what
each guardrail catches and what it does not; which you proved by breaking and
which you could not; what you deleted; and what you found in the audit but
deliberately did not act on. List every claim you could not verify. Recommend
nothing you have not tested.