The first guide covered how to structure a vault that a human and an AI agent can both read. This one covers the harder half: getting agents to keep it that way. A structure that only holds while you are watching is not a structure, it is a preference. What follows is the instruction, tooling, enforcement, and audit layer that turns your conventions into something an agent follows on session 400 as reliably as on session 1.


Why Documentation Isn't Enough #

Every agent session is a new hire who read the handbook once, has no memory of yesterday, and never gets a performance review. Write the best conventions doc in the world and you will still watch notes land in the wrong folder. There are only three reasons it happens, and each has a different fix:

FailureWhat it looks likeFix layer
Never readThe rule is on line 340 of a 600-line file, or in a folder the agent never openedHierarchy + budget
Read but outrankedA generic instinct ("docs go in Reference/") beats your specific decision treeExplicit precedence + negative space
Followed, then driftedCorrect for a month, then the folder layout changed and the doc didn'tAudit + watchdogs

The mistake is treating this as a prompt-engineering problem. It is a systems problem. You do not fix drift by writing a firmer sentence; you fix it by making the wrong action harder than the right one, and by finding out within a week when it happens anyway.

⚠️
The Rule About Rules
Anything you are not willing to enforce, do not write down. An unenforced rule is a claim your future agent will believe and act on. One stale sentence in an entry file can misfile a hundred notes before you notice.

The Five Layers #

An agent-operable vault is five layers deep. Each one catches what the layer below it misses.

5  AUDIT         drift reports, freshness checks, link audits
   └─ catches what leaked through everything else

4  ENFORCEMENT   write hooks, path guards, frontmatter validators
   └─ blocks the write that breaks the convention

3  TOOLS         write wrapper, search CLI, templates
   └─ makes the correct action the path of least resistance

2  CONTEXT       index files, AI-context tier, memory index
   └─ the agent knows what already exists

1  INSTRUCTIONS  entry file, rules directory, per-folder filing rules
   └─ the agent knows the conventions

Most people build layer 1, skip to complaining, and never build 2 through 5. Layer 1 alone gets you compliance on a quiet day and nothing on a busy one, because a long, complicated task pushes your conventions out of the agent's working attention exactly when it is creating the most files.

Build them in order, but do not skip layer 5. Audit is the only layer that tells you whether the other four are working.


The Instruction Hierarchy #

One giant instructions file does not scale. Split by scope and lifetime, so that each file can be edited without re-reading the others, and so an agent working in one corner of the vault loads only what applies there.

ScopeFileContainsChanges
Machine~/.agent/INSTRUCTIONS.mdWho you are, key paths, delegation policy, tool triggersMonthly
Concern~/.agent/rules/*.mdOne file per concern: safety, file hygiene, code quality, workflow, deploysWeekly
Vault<vault>/CLAUDE.mdStructure, naming, note anatomy, filing tree, entry points, commandsQuarterly
Folder<folder>/Filing-Rules.mdSubfolder map for this project, and what does not belong herePer project
Notefrontmattertype, status, confidence, datesEvery edit

Split the Rules Directory by Concern, Not by Topic

A rules/ directory of five to seven small files beats one long document for a practical reason: you can replace safety.md wholesale after an incident without touching anything else, and a sync script can inject a shared block into one file across every agent on the fleet. Keep each under about 40 lines. Suggested split:

rules/safety.md         destructive commands, secrets, confirmations
rules/file-hygiene.md   where scratch files go, no litter in $HOME, log paths
rules/code-quality.md   read before edit, root causes, minimal diffs
rules/workflow.md       plan → explore → implement → test → verify
rules/deployment.md     which service restarts on which change
rules/mistakes.md       the corrections ledger (see section 12)

State Precedence Explicitly

If two files disagree, the agent will guess, and it will guess differently each time. Put one paragraph near the top of your entry file:

## Precedence

Most specific wins. A folder's Filing-Rules.md overrides the vault
CLAUDE.md, which overrides machine-level rules, which override your
default instincts. If a rule here conflicts with what you would
normally do, this file wins — do not "improve" on it.
💡
Budget the Entry File
The entry file is loaded on every single turn. It competes for attention with the actual task. Cap it — roughly 300–400 lines — and make everything past that a pointer: "Trading conventions: read 04-Domain/CONVENTIONS.md when working in that folder." A pointer that gets read beats a section that gets skimmed.

Rules an Agent Will Follow #

Instructions written for humans and instructions written for agents fail differently. Humans fill gaps with judgment. Agents fill gaps with the average of everything they have ever read, which is exactly the generic convention you are trying to override.

Instead ofWriteWhy
"Notes should be well organized""File by subject, not by note-type. Decision tree below, stop at first match."Aspiration is not a rule. A tree is executable.
A paragraph describing where things goA numbered decision tableTables are read in order; prose is skimmed for keywords
"the vault", "the project folder"~/vault/02-Projects/<Project>/Relative references resolve differently per session
"Avoid editing files directly""Direct edits are blocked by the write hook. Use vault-write <rel-path>."Name the mechanism and the alternative, or it reads as a suggestion
A rule with no rationaleThe rule + one clause of whyAgents generalize from the why to the cases you forgot to list

Negative Space Is Load-Bearing

Misfiling is a boundary problem, not a naming problem. Agents rarely invent an absurd location; they pick the plausible neighbor. A short "What does NOT go here" list prevents more misfiles than doubling the length of the positive list:

## What does NOT go here

- General domain research spanning projects   04-Domain/Research/
- Cross-project postmortems                   07-Reference/Lessons/
- Fleet-wide agent or model decisions         08-AI/Decisions/
- Anything about the hardware, not the app    05-Infrastructure/

Note the shape: each line is a near miss plus its correct destination. Do not list absurd alternatives; list the ones you have actually seen an agent choose.

One Fact Per Line

Compound sentences hide rules. "Use ISO dates and Title Case for note names, except programmatic files which use hyphens" contains three rules and one exception, and an agent will reliably retrieve two of them. Split it:

# Bad: one sentence, four facts
Use ISO dates and Title Case, except programmatic files use hyphens.

# Good: four lines, four facts
- Dates are always YYYY-MM-DD.
- Human-facing note names use Title Case.
- Programmatic files use hyphens, lowercase.
- The filename must match the `# Title` inside the note.

The Context Tier #

Rules tell an agent how to file. The context tier tells it what already exists — which is what stops it creating a fourth note on a subject that already has three.

Three Artifacts

ArtifactBuilt bySizeLoaded
09-AI-Context/*.mdHand, reviewed on a schedule~50 lines eachWhole folder, at session start
.vault-index.mdScript, on a cronOne line per noteGrepped, never read whole
Memory indexAgent, gated by rulesHard cap in lines and KBEvery turn

The Generated Index

A flat, greppable index is worth more than any clever retrieval scheme, because it costs one grep instead of a directory walk. One line per note: path, then the first meaningful line of the note.

# Vault Index — auto-generated, do not edit
Total notes: 4,906 · rebuilt 2026-08-21

## 02-Projects
- **02-Projects/Atlas/README.md**: Status active. Phase 2 — ingestion rewrite…
- **02-Projects/Atlas/Decisions/2026-07-14-Storage.md**: Chose object store over…

Rebuild it on a schedule, and put the rebuild command in the entry file so an agent can refresh it after a bulk change instead of working from a stale map.

Hot and Cold Tiers

The memory index is loaded every turn, so it has a hard budget. Keep the categories you consult constantly in the hot file, and move everything else into per-category sub-index files that are read only on topic match:

# Memory Index — Hot Tier
Cap: 200 lines / 25KB. One line per memory. Hooks only, never content.

## Working Style
- [feedback-search-before-write.md](…) — Grep for existing coverage before adding a note.

## Cold Tier — load on demand
- Infrastructure (~69 entries)  index/infrastructure.md
- Project Status  (~70 entries)  index/project-status.md
⚠️
Context Files Rot Silently
Nothing breaks when a context file is wrong — the agent just confidently acts on last quarter's project list. Stamp every context file with a date and audit anything older than 14 days. This one check has caught projects marked "retired" that had been live for two months.

Machine-Readable Filing Rules #

The vault-wide decision tree gets a note into the right folder. Inside a mature project folder there are eight subfolders and the tree has nothing to say about them. That is what a per-folder Filing-Rules.md is for — and it is written twice on purpose: once for the validator, once for the agent.

---
title: Atlas — Filing Rules
project: Atlas
updated: 2026-08-21
# sanctioned: machine-readable allowlist. Keep in sync with the table below.
sanctioned: [01-Architecture, 02-Strategy, 03-Engineering, 04-Research,
              05-Decisions, 06-Design, 08-Lessons, 09-Handoffs]
---

# Atlas — Filing Rules

> Where things go inside `02-Projects/Atlas/`. Tightens the vault decision tree.

## Subfolder map

| Subfolder | Goes here |
|---|---|
| `01-Architecture/` | Cross-cutting specs, data inventory, integration maps. Not version-specific. |
| `05-Decisions/`    | One file per decision. `YYYY-MM-DD-<Slug>.md`. Rationale + rejected alternatives. |
| `08-Lessons/`      | Postmortems for THIS project. Cross-project lessons go to 07-Reference. |

## What does NOT go here
(near misses + their correct destination)

## When to update README vs Tasks
- README changes when **strategy** changes.
- Tasks changes **every time you touch the project**.

The sanctioned list is what a write hook checks: a path whose subfolder is not on the list is a violation, no language understanding required. The prose table is what the agent reasons with when choosing among the sanctioned options. Both must exist. A machine list alone produces valid-but-nonsensical filing; prose alone produces nothing a guard can check.

ℹ️
Two Copies, One Truth
Any time a fact exists in two places it will drift. Put the "keep in sync" comment inside the frontmatter where an editing agent cannot miss it, and have the weekly audit diff the allowlist against the folders that actually exist on disk.

Give Agents a Write API, Not a Filesystem #

Native file-writing tools will write any bytes to any path. There is nowhere to hang validation. The single highest-leverage piece of infrastructure in an agent-operable vault is a write wrapper: one command that every agent, script, and cron uses to create or replace a note.

What the Wrapper Does

  1. Resolves the path relative to the vault root, and refuses anything that escapes it
  2. Takes a per-file lock (an atomic mkdir is enough) so two agents cannot interleave writes
  3. Writes to a temp file, then renames — readers and sync clients never see a half-written note
  4. Validates frontmatter: required keys, date format, tag vocabulary
  5. Checks the path against filing rules, warn or reject depending on mode
  6. Logs every write: timestamp, path, caller, verdict
  7. Optionally triggers sync so a note is on your phone before you stand up
# Usage the agent is taught in the entry file
vault-write 02-Projects/Atlas/05-Decisions/2026-08-21-Storage.md < /tmp/draft.md
vault-write --enforce 04-Domain/Research/VPIN-Study.md < /tmp/study.md
vault-edit  --dry-run 02-Projects/Atlas/README.md
vault-write --force --force-reason "one-off migration" path/to/note.md

Exit Codes Are the API

Agents branch on exit codes far more reliably than on prose. Make them mean something specific and document them in the tool's own help text:

CodeMeaningWhat the agent should do
0Written and validContinue
1Generic error (path outside vault)Fix the path, retry
2Filing-rules reject, nothing writtenRe-read Filing-Rules.md, choose a sanctioned folder
3Lock timeoutAnother writer is active. Wait, retry once, then report
4Written, but frontmatter warnings on stderrFix the frontmatter in a follow-up edit
🛑
Never Build Note Content in a Shell Heredoc
Long heredocs piped into a file truncate silently — you get a note that ends mid-sentence and no error anywhere. Stage the content to a temp file with a real write tool, then pipe that file into the wrapper. This is the single most common way agents corrupt long notes.
⚠️
Absolute Paths in Rules
Your shell's PATH is not the agent's. In cron jobs, launchd agents, and non-interactive SSH one-shots, ~/bin is usually absent — a bare vault-write fails with "command not found" and the automation silently does nothing. Always write the absolute path in instructions and scripts.

Search Before Read #

The read path needs a tool as much as the write path does. Without one, an agent's instinct is to list directories and open files until it finds something — which burns context and, worse, often stops at the first plausible match instead of the right one.

Give it one ranked-search command and teach the sequence:

1. vault-search "query" [max]    ranked matches with snippets
2. grep "topic" .vault-index.md   one-line summaries, cheap
3. read <specific note>          only what step 1 or 2 identified

# Budget: 3–5 files per turn unless the task genuinely demands more.

Two flags earn their keep: a --files mode that returns paths only (for when the agent is going to read them anyway), and a relevance mode backed by the OS indexer for fuzzy recall. Both reduce the "open six notes to find one" pattern.

💡
An Empty Result Is a Claim, Not a Fact
Teach agents that "no matches" means the search returned nothing, not the note does not exist. Index staleness, a wrong root, and a quoting bug all look identical to absence. Before concluding something is missing, confirm the tool works with a query you know matches, or fall back to a filename search.

Enforcement Hooks #

Hooks are the layer that converts a convention into a fact. They intercept tool calls before or after execution and can block, warn, or transform. Most agent runtimes expose the same four moments:

MomentUse it forExamples
Session startInjecting contextLoad rules directory, print vault status, warn on stale index
Before tool useBlockingPath guard, dangerous-command block, secret scan, branch protection
After tool useValidating and fixingFrontmatter validator, auto-format, large-file warning, diff-size warning
On stopNotifyingPush a summary, log the session, flag unfinished work

The Guard Set Worth Building First

  • Path guard — block native writes to vault paths so everything goes through the wrapper
  • Frontmatter validator — after any .md write, check required keys and at least one wikilink; skip templates, daily notes, and archive
  • Secret scan — block writes and commits containing key-shaped strings
  • Home-directory litter guard — refuse new files at the top level of $HOME
  • Destructive-command block — require an explicit confirmation path for recursive deletes and force pushes

The Block Message Is the Fix Instruction

When a hook blocks, its message is the only thing the agent sees. Written badly, it produces three retries and a workaround. Written well, it produces a correction:

# Bad
"Blocked: write not permitted."

# Good
"Blocked: direct writes to ~/vault are disabled (sync lock safety).
 Stage the content to /tmp/<name>.md, then run:
   ~/bin/vault-write <path-relative-to-vault> < /tmp/<name>.md
 Path must be under a sanctioned subfolder: see <project>/Filing-Rules.md"

Three Gotchas That Cost Real Hours

GotchaSymptomHandling
Hooks fire on the tool, not the intentThe write hook is bypassed by cat > file in a shell callGuard the shell tool too, matching on the path, not the verb
Hook working directoryA repo/branch check misidentifies state because the hook runs from the session's launch directory, not the command'sParse the leading cd out of the command, and keep sibling hooks consistent
A block kills the whole commandA compound commit && push is rejected, and you cannot tell which half tripped itInstruct agents to keep guarded operations in separate calls

Rollout Without Revolt #

Turning on enforcement the day you write the rules is how you end up disabling it a week later. Ship guards in two phases.

Phase 1 — Warn Only

The guard runs, evaluates, logs its verdict, and lets the write through. Run it for two weeks and read the log. It answers a question you cannot answer from intuition: where do agents actually disagree with your taxonomy?

# One line per evaluated write
2026-08-14T09:12:04 WARN  02-Projects/Atlas/notes/x.md  # 'notes' not sanctioned
2026-08-14T11:40:55 OK    02-Projects/Atlas/05-Decisions/2026-08-14-Cache.md
2026-08-15T08:03:11 WARN  07-Reference/atlas-postmortem.md  # project-scoped

Then triage the top violations honestly. If the same "wrong" destination shows up twenty times, there are two possibilities, and the boring one is usually correct: your taxonomy is missing a folder. Fix the rule before you enforce it.

Phase 2 — Enforce, Selectively

Flip enforcement on per folder, starting with the ones whose taxonomy has been stable for a month. Leave new or churning areas in warn-only. Enforcement is not all-or-nothing, and treating it that way is why most people never get past phase 1.

💡
Always Ship the Escape Hatch
Keep a --force flag that records a reason to the log. A guard with no override gets disabled entirely the first time it is wrong at 2am — and it will be wrong at 2am. A forced write with a logged reason is data; a disabled guard is a blind spot.

Drift Watchdogs #

Everything above is preventive. Layer 5 assumes prevention leaks — because it does — and finds the leaks on a schedule.

AuditCadenceLooks for
Filing driftWeeklyNotes outside sanctioned subfolders, folders missing from allowlists
Index reachabilityWeeklyMemories or notes reachable from no index, broken wikilinks, stray backups
Context freshnessWeeklyContext files older than 14 days, or stubs that lost their content to sync
Orphan notesMonthlyZero in and out links — link them or archive them
Tag auditQuarterlyOne-off tags, near-duplicates, tags with a single note
Restore testAnnuallyThat your backup actually restores

Report Format

An audit that produces a wall of findings gets ignored by week three. Cap it, sort by severity, and pair every finding with one concrete action:

Filing Drift — week of 2026-08-17

3 misfiled   07-Reference/atlas-postmortem.md    02-Projects/Atlas/08-Lessons/
1 unsanctioned 02-Projects/Atlas/notes/          add to allowlist or merge
2 stale      09-AI-Context/projects.md (31d)     refresh or mark unmaintained

Nothing else drifted. Previous week: 5 findings, 4 resolved.
🛑
A Dead Watchdog and a Clean Vault Look Identical
Silence from a monitor is not good news — it is no news. Scheduled jobs vanish in crontab rewrites and stay gone for months. Give every watchdog a liveness check: it writes a heartbeat line each run, and a second, separate check alerts if that log is older than twice the interval. Re-grep for every watchdog entry after any schedule edit.

The Corrections Ledger #

Corrections you make in conversation die with the session. The ledger is a single append-only file of hard-won rules, injected into every agent's instruction set by a sync script. It is the mechanism by which the fleet gets smarter instead of repeating the same failure across five agents.

The Grammar

One line. Date, scope tag, the trap, the rule, and how to verify. The trap comes first because that is what a future agent will pattern-match on:

- 2026-08-19 [all] A config validator that exits 0 on broken YAML gives you a
  service running on defaults while reporting healthy — parse the file with a
  real YAML loader before every reload, not the vendor's own check. (src: cc)

- 2026-08-15 [all] In cron, launchd, and SSH one-shots, ~/bin is NOT on PATH —
  always use absolute paths in scheduled jobs. (src: cc)

The Gate

Not every correction belongs here, or the file becomes noise nobody loads. Three questions:

QuestionIf no
Would this recur on a different project or machine?Project lessons file
Was it non-obvious — would a careful agent still hit it?Skip it
Is it about the fleet rather than about you?Agent memory (feedback-*)
⚠️
Sync Scripts Must Discover Targets by Glob
A distribution script with a hardcoded list of agent directories goes stale the moment you add an agent — and the new agents end up with zero ledger rules while the script reports success. Enumerate targets with a glob, and verify after each run that the managed block actually landed in every file.

Memory vs Vault #

Agents with persistent memory will happily write everything into it, and then you have two knowledge bases that disagree. Draw the line once, in the entry file:

Agent memoryVault
SubjectYou, and how to work with youThe world, and the work itself
ExamplesPreferences, corrections, tool traps, project constraints not visible in codeResearch, decisions, incidents, meetings, references
SizeOne fact per file, indexedFull notes with structure
AudienceAgents onlyYou first, agents second

The Write Gate

Memory grows monotonically unless you gate it. Before creating any memory, the agent should search existing ones and prefer, in order:

  1. Update — extend or correct the existing file and its index line
  2. Supersede — annotate the old file as superseded, keep it, link forward
  3. No-op — already covered, do nothing
  4. Add — only if none of the above apply, and it must include an index line

Do not store what the repository already records — code structure, past fixes, git history. Those are cheaper to re-derive than to keep true.

ℹ️
Memories Are Stamped in Time
A memory reflects what was true when it was written. If one names a file, flag, or service, verify it still exists before acting on it. Treat recalled memory as a strong prior, never as current state.

One Canonical Source #

Once more than one runtime reads your conventions — a CLI agent, a messaging agent, a scheduled worker — the failure mode changes shape. It stops being "the agent ignored the rule" and becomes "the agent read a different copy of the rule."

vault/08-AI/Skills/          ← CANONICAL. Edit only here.
        
        ├─ sync  ~/.agent-a/skills/   real copies, refreshed by a script
        ├─ read  agent-b external_dirs points at canonical, no copy
        └─ read  agent-c extraDirs     points at canonical, no copy

Three rules keep this honest:

  • Edit canonical, then run the sync. If the copies are real files rather than links, an unsynced edit never reaches the agent, and everything looks fine.
  • Never let one runtime load the same rule from two places. Dual-loading produces duplicate names, and ambiguous names get silently skipped — scheduled jobs then run without the instructions they were designed around.
  • Verify after sync, do not assume. Check that the managed block is present in each target, with the expected date.
⚠️
Cloud-Synced Folders Are Not Neutral
If your vault or rules live in a cloud-sync folder, expect evicted placeholder files that read as empty, cooperative-lock errors under concurrent writes, and multi-minute stalls on session start when an agent walks the tree. A local directory plus a file-sync tool avoids all three.

Session Rituals #

Structure decays at the boundaries of a session: the start, where an agent has no context, and the end, where everything it learned evaporates. Both deserve an explicit routine.

MomentRitualAutomate with
Session startLoad rules, memory index, and the context tier; flag anything staleSession-start hook
First touch of a folderRead that folder's Filing-Rules.md before writing into itA rule + the write wrapper's reject message
Session endCompress the session into a dated note; append durable lessonsA "compress" command
Work continues tomorrowWrite a handoff note: state, open questions, next actionA "handoff" command
WeeklyReview the drift report; update project statuses; archive stale draftsScheduled job

The handoff note is the highest-value of these and the most often skipped. Its test is simple: a fresh agent, given only this note, can resume the work without asking you anything. If it cannot, the note is a summary, not a handoff.


Testing Agent-Readiness #

You cannot tell whether your conventions work by reading them. You have to run them. Open a fresh session with no conversation context and hand it five filing tasks whose correct answers you already know:

1. A postmortem for an outage in one specific project
2. A troubleshooting writeup for one piece of hardware
3. A pattern that genuinely spans three projects
4. Context about a person you just met
5. A research result tied to one strategy

Score each on: folder · filename · frontmatter · wikilinks · index updated

Tasks 1 and 3 are the ones that matter — they sit on the boundary between project-scoped and cross-cutting, which is where every taxonomy leaks. Anything less than a clean pass is a documentation bug, not an agent bug. Fix the sentence that failed, then re-run the same five.

💡
Read the Reasoning, Not Just the Result
When an agent files something wrong, its explanation tells you which sentence it anchored on. That sentence is the bug. A right answer for the wrong reason is worth investigating too — it will be a wrong answer next week, on a slightly different note.

Re-run the eval after any structural change: a new top-level folder, a renamed project, a rewritten decision tree. It takes ten minutes and it is the only measurement in this guide that tests the whole stack end to end.


Anti-Patterns #

Don't do thisWhy it hurts
Rules that live only in chat historyThey expire with the session. If it matters twice, it goes in a file.
One 900-line instruction fileLoaded every turn, skimmed every turn, edited by nobody
Enforcement with no overrideGets disabled wholesale the first time it is wrong
A watchdog with no liveness checkSilence reads as health. It can be dead for months.
The same rule in two filesThey drift, and the agent picks the wrong one at random
Rules describing the vault you wish you hadTrains agents that your instructions are approximations
A block message with no alternativeProduces retries and workarounds instead of corrections
A generated index nobody rebuildsWorse than no index: it is confidently out of date
Agent memory as a dumping groundUnindexed memories are unrecallable; volume crowds out signal
Bulk-reorganizing before the rules are settledYou will move everything twice. Warn-only first, then move.

Implementation Checklist #

In order. Each step is useful on its own, and each one makes the next cheaper.

  • Split your instructions into an entry file plus a rules/ directory
  • Add an explicit precedence paragraph to the entry file
  • Cap the entry file and convert the overflow into pointers
  • Write Filing-Rules.md for your three busiest folders, with a sanctioned list
  • Add a "What does NOT go here" section to each one
  • Build the write wrapper: lock, atomic rename, validate, log
  • Document its exit codes in the entry file
  • Add a search command and teach the search-before-read sequence
  • Generate .vault-index.md on a schedule
  • Turn on the path guard and frontmatter validator in warn-only mode
  • Read the warn log after two weeks; fix the rules it exposes
  • Flip enforcement on for the folders with a settled taxonomy
  • Schedule the weekly drift audit, and give it a liveness check
  • Start the corrections ledger and wire its sync
  • Run the five-task eval. Fix what fails. Re-run.

Further Reading #