commit b5e3dbe614fa114425c1ab943a439ac7cff601f6 Author: gramps Date: Fri Oct 30 06:51:19 2026 -0700 Seed an AI-legible project memory map that stays small One file (AGENTS.md) that bootstraps the rest: rules, the file map to create, what belongs in each file, the first-session interview order, and the list of anti-patterns that killed the previous map (1,308-line guide, 63 task files, narrative history inline, sessions skimming 56k tokens of context). Separates four kinds of content by read frequency: rules/invariants -> AGENTS.md (every session) subsystem truth -> docs/ai/.md (only the matching one) lookups -> environment.md (grepped, never read) retired decisions -> decisions.md (only when re-opening one) Caps are enforced, not promised: scripts/verify.sh checks doc budgets before the build, so a commit that pads a capped file fails. Proven both ways — it passes clean and exits 1 on an over-cap file. scripts/scope-check.sh blocks edits outside the declared file list. templates/ holds fill-in skeletons for the seven files a project must create. CC0: copy it, rename it, sell it, no attribution needed. diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000..6bc5c11 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,145 @@ +# AGENTS — bootstrap + +You are starting this project's memory from nothing. This file is self-contained: it gives you +the rules, the file map you must create, what belongs in each file, and the order to do it in. + +Two standing orders: + +1. **This file is the only mandatory read at session start.** Everything else is read on demand. +2. **Finish work; do not manage it.** A session that produces task lists, re-prioritisation or + documentation of work instead of working has failed, even if the docs are good. + +--- + +## 1. Rules — non-negotiable + +**Delivery** +- One unit = one behaviour = **one test** = one commit. If a request needs several tests, pick the + one the user cares about and finish it before the next. +- No feature branches pre-1.0. Work lands on `main`, committed per unit. +- Commit every unit without asking. **Push only at checkpoints the user names.** +- Declare the exact file list before editing. No "while I'm here" edits, no drive-by refactors. + Anything spotted outside the list becomes a one-line follow-up in `HANDOFF.md`. +- One pre-commit gate for code: clean build at **0 warnings**, full tests, scope check, doc budgets + (`scripts/verify.sh ""`). Docs-only units run the scope check alone. + +**Reading** +- Session start, in this order, and stop: `HANDOFF.md` → `ai.md` → **the one** `docs/ai/.md` + that matches the task → `/index.md` for the code you will touch. +- `TASKS.md` is read when the question is "what's next" — never as a prerequisite to code. +- Never read the whole map "for context". If the map is a required read, the map is wrong. + +**Memory** +- The map is corrected by the change that **falsifies** it — in the same commit. It is not a unit + of its own; no "docs backfill" commits unless asked. +- Three kinds of truth, three homes: rules/invariants → this file; subsystem detail → + `docs/ai/.md`; lookups (paths, ports, hosts, credential locations) → one cheat sheet. + History and abandoned decisions → a decisions log, never inline in the docs. +- `HANDOFF.md` is current state only, **overwritten not appended**, hard-capped. +- A fact recorded once ends the re-derivation loop: paths, traps and recipes go in the map the + first time they cost a hunt. **Grep the recipes file before re-deriving anything.** + +**Behaviour** +- Do the work, then report what changed and what's next. No plans, pros/cons tables or "pitfalls" + sections unless asked. +- Nothing here is novel: scan externally before building anything new, cite the reference in the + commit. A **second** failed fix for the same symptom is a research trigger, not a persistence + trigger — stop and find the established answer. +- Follow the codebase's existing conventions; don't add comments the code doesn't need; don't + invent work items. + +--- + +## 2. Files you must create + +| File | Role | Cap | Written by | +|---|---|---|---| +| `AGENTS.md` | This file: rules + the project's invariants | 210 lines | you, rarely | +| `ai.md` | **Router**: what the product is, build commands, architecture table, where truth lives | 100 lines | you, rarely | +| `HANDOFF.md` | Current state: branch, in flight, next action, landmines | 40 lines | every session, overwritten | +| `TASKS.md` | The active queue, one line per live item | 120 lines | on status change | +| `TASKS/archive.md` | Everything done, as a dated snapshot | unbounded | at trim time | +| `docs/ai/.md` | Subsystem truth — one file per subsystem | unbounded | as that subsystem changes | +| `docs/ai/index.md` | Routing table: file ↔ what it covers ↔ when to read it | — | as files are added | +| `docs/ai/decisions.md` | Retired paths + cause of death, and the permanent out-of-scope list | — | when a decision dies | +| `docs/ai/environment.md` | Lookups: hosts, ports, paths, build/run/test commands, suite map | — | when a fact costs a hunt | +| `MyMistakes.md` | Failure log + **recipes registry** (grep-first) | — | when something is learned the hard way | +| `schema.md` | The conventions above, restated for this repo | — | once | +| `/index.md` | One per code directory: file list + one-line purpose + links out | — | when layout changes | + +If a file is over cap: **move detail out, never pad** — the gate fails padding. + +--- + +## 3. What goes in each file + +**`HANDOFF.md`** (≤40) +``` +# HANDOFF — () +## State branch, worktree, unpushed commits +## Next action the single next unit, and why it is next +## Landmines live traps only — paths, flaky tests, do-not-touch rules +## Pending what is blocked on the user (checks, decisions, takes) +``` + +**`ai.md`** (≤100) — `# — AI guide & router`, then: +- `## What it is` — five lines max. +- `## Build, run, test` — the actual commands, plus the pointer to `environment.md`. +- `## Architecture` — one table row per top-level directory: path → role. +- `## Where the truth lives` — table: subsystem → doc → "read when". +- `## Current state` → a one-line pointer to `HANDOFF.md`. Nothing else. + +**`docs/ai/.md`** — open with one line of "read when". Then observed reality only: +how it works, the traps that cost time, the measurements that settled an argument, and the +guard test that protects each rule. Date contested facts. Never re-tell the product pitch. + +**`TASKS.md`** — `## Next up` (the one unit, 5 lines) · `## Queue` (one table row per item: +id, status ☐🔶⏳⏸❌, one-line scope, detail link) · `## Pending the user` · `## Release gates`. + +**`decisions.md`** — one dated line per decision that no longer governs, with the reason it died, +plus the permanent out-of-scope list. Read only when about to re-open one. + +**`MyMistakes.md`** — `## Recipes` first (how-to, verbatim commands, traps). Then dated failure +entries: symptom → wrong guess → actual cause → the rule that prevents it. + +--- + +## 4. Create the gate + +`scripts/scope-check.sh` — fails if any changed file is outside the declared list. +`scripts/verify.sh ""` — in this order: + +1. **Doc budgets**: `wc -l` every capped file, fail with "move the detail out, do not pad". +2. **Clean build**: clean first, then build; any warning fails. (Incremental "0 warnings" lies.) +3. **Tests**: full suite; a whitelist of known-flaky names, everything else is a regression. +4. **Scope check** with the passed file list. + +A budget that is not a failing gate gets eaten by the next append. This is the load-bearing part. + +--- + +## 5. First session — do this, in order + +1. Ask the user for: what the product is in one paragraph, the architecture's top-level + directories, the build/run/test commands, the deployment target, and anything that must never + be violated (legal, data-loss, output-corrupting). **One question at a time.** +2. Write `AGENTS.md` §1 rules as-is, then add **the invariants**: 10–20 lines, each stating a rule + and pointing at the doc that explains it. An invariant earns its line only if violating it + breaks output, destroys user data, or creates a legal/trust breach. +3. Write `ai.md` router, `HANDOFF.md`, `TASKS.md` (empty queue), `docs/ai/index.md`, + `docs/ai/environment.md`, `decisions.md` skeleton, `MyMistakes.md` with an empty Recipes + section, `schema.md`, and `/index.md` for each directory. +4. Write the two scripts and prove the gate fires (create an over-cap file, watch it fail). +5. Commit once: "docs: project memory map + gate". Then **stop mapping and start working**. + +--- + +## 6. Anti-patterns that killed the last map + +- Appending instead of replacing — the file only grows, and stale facts outlive the code. +- One task file per task, with paragraph-length status prose — a second, worse source of truth. +- Cross-references like "TASK 3 item 17" — numbers rot; cite a path or a feature name. +- Narrative history kept inline "for context" — it is 30% of the file and read by nobody. +- Splitting into more files without a router — discovery cost just moved. +- Docs commits as units of work — the cheapest thing to produce, so it replaces real progress. +- Reading the whole map every session — a tax that trains sessions to skim. diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..ec51815 --- /dev/null +++ b/LICENSE @@ -0,0 +1,20 @@ +CC0 1.0 Universal (CC0 1.0) — Public Domain Dedication +https://creativecommons.org/publicdomain/zero/1.0/legalcode + +The person who associated a work with this deed has dedicated the work to the +public domain by waiving all of his or her rights to the work worldwide under +copyright law, including all related and neighboring rights, to the extent +allowed by law. + +You can copy, modify, distribute and perform the work, even for commercial +purposes, all without asking permission. + +In no way are the patent or trademark rights of any person affected by CC0, nor +are the rights that other persons may have in the work or in how the work is +used, such as publicity or privacy rights. + +Unless expressly stated otherwise, the person who associated a work with this +deed makes no warranties about the work, and disclaims liability for all uses of +the work, to the fullest extent permitted by applicable law. + +The full legal text of CC0 1.0 Universal is at the URL above. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ba1b5b0 --- /dev/null +++ b/README.md @@ -0,0 +1,63 @@ +# agent-memory-seed + +Seed for an AI-legible project memory map: **fork it, don't sync it.** + +Copy the files into a new repo, let the AI run the first-session interview, then delete the seed +scaffolding. Every project owns its own copy from then on; improvements that prove out somewhere +get brought back here deliberately, one at a time. Never try to keep the two in lockstep. + +## Why it exists + +Most "AI context" files die the same death: they grow. A rules file becomes a history file, a task +list becomes a second source of truth, and every session pays to skim it — which is how stale facts +survive. This seed is small because it separates four kinds of content that have four different +read frequencies: + +| Kind | Home | Read | +|---|---|---| +| Rules + invariants | `AGENTS.md` | every session | +| Subsystem truth | `docs/ai/.md` | only the one matching the task | +| Lookups (hosts, paths, commands) | `docs/ai/environment.md` | grepped, never read | +| Retired decisions | `docs/ai/decisions.md` | only when re-opening one | + +Caps are enforced by `scripts/verify.sh`, not promised: a commit that pads a capped file fails. + +## What's here + +``` +AGENTS.md the seed: rules, file map, per-file contents, first-session order +scripts/verify.sh the one gate — doc budgets, clean build, tests, scope check +scripts/scope-check.sh fails if a commit touches files outside the declared list +templates/ fill-in skeletons the AI copies into the target project +``` + +## Use + +```bash +git clone https:////agent-memory-seed.git +cd +rm -rf .git && git init -b main +``` + +Then, as the first prompt to the AI: + +> Read AGENTS.md and follow it. Ask me the first-session questions one at a time, then build the +> memory map, then delete the seed scaffolding — `templates/` and the seed sections of README. + +`templates/` is input, not output: copy each skeleton to its real path (`templates/handoff.md` → +`HANDOFF.md`) and fill it in. When the map is built, remove `templates/` and rewrite this README +for the actual project. + +## The parts that matter most + +1. **The caps + the gate.** Everything else degrades politely; a file without a failing check + bloats silently. +2. **`HANDOFF.md` is overwritten, never appended.** History belongs to `git log`. +3. **A budget cut means moving detail out, never deleting a fact** — out to a subsystem doc, a + lookup sheet, the decisions log, or git. + +Anti-patterns and the full ruleset live in [`AGENTS.md`](AGENTS.md) §1 and §6. + +## License + +[CC0 1.0 Universal](LICENSE) — public domain. Copy it, rename it, sell it, no attribution needed. diff --git a/scripts/scope-check.sh b/scripts/scope-check.sh new file mode 100644 index 0000000..55aaec4 --- /dev/null +++ b/scripts/scope-check.sh @@ -0,0 +1,57 @@ +#!/usr/bin/env bash +# scope-check.sh — Validate that git diff only touches declared files. +# Usage: ./scripts/scope-check.sh "file1.cs" "file2.cs" ... +# Exit 0 if all changed files are in scope, 1 if any are outside. +# +# Checks staged, unstaged, and untracked changes against the allowed list. +# Supports glob patterns in the allowed list (e.g. "ytLive.Tests/*"). + +set -euo pipefail + +if [ $# -eq 0 ]; then + echo "Usage: $0 \"file1.cs\" \"file2.cs\" ..." + echo " Pass the declared file list as arguments." + exit 1 +fi + +# Collect allowed patterns into an array +allowed=("$@") + +# Gather all changed files: working tree vs HEAD (tracked) + staged + untracked +changed=$({ + git diff --name-only HEAD 2>/dev/null || true + git diff --name-only --cached 2>/dev/null || true + git ls-files --others --exclude-standard 2>/dev/null || true +} | sort -u) + +if [ -z "$changed" ]; then + echo "✓ No changes detected." + exit 0 +fi + +violations=() +while IFS= read -r file; do + matched=false + for pattern in "${allowed[@]}"; do + if [[ "$file" == $pattern ]]; then + matched=true + break + fi + done + if [ "$matched" = false ]; then + violations+=("$file") + fi +done <<< "$changed" + +if [ ${#violations[@]} -eq 0 ]; then + echo "✓ Scope check passed — all changed files are in scope." + exit 0 +fi + +echo "✗ SCOPE VIOLATION — the following files are outside the declared scope:" +for f in "${violations[@]}"; do + echo " - $f" +done +echo "" +echo "Either justify the edit or revert the change." +exit 1 diff --git a/scripts/verify.sh b/scripts/verify.sh new file mode 100644 index 0000000..2e64deb --- /dev/null +++ b/scripts/verify.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +# verify.sh — the one gate before committing: doc budgets + clean build + tests + scope check. +# Usage: ./scripts/verify.sh "path/changed1" "path/changed2" ... +# +# Why a CLEAN build? An incremental build skips recompiling, so a "0 warnings" report can be a lie +# — a nullable warning slipped past exactly that way once. Clean first, then build. +# +# CONFIGURE the three commands below for the project. Empty means "skip with a warning", so a +# docs-only repo works out of the box. + +set -euo pipefail + +CLEAN_CMD="" # e.g. 'dotnet clean App.csproj' +BUILD_CMD="" # e.g. 'dotnet build App.csproj' +TEST_CMD="" # e.g. 'dotnet test Tests/Tests.csproj' +WARN_PATTERN=": warning" # what a compiler warning looks like in BUILD_CMD output +KNOWN_FLAKY="" # regex of pre-existing flaky test names; anything else fails the gate + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT" + +echo "══ 1/4 DOC BUDGETS ══" +# The map stays cheap to read. A commit that PADS a capped file instead of moving detail out +# fails here (see AGENTS.md -> Reading budget). +check_budget() { + local rel="$1" cap="$2" lines + [ -f "$ROOT/$rel" ] || { echo " ⚠ $rel not built yet — skipped"; return 0; } + lines=$(wc -l < "$ROOT/$rel") + if [ "$lines" -gt "$cap" ]; then + echo "✗ $rel is $lines lines (cap $cap)." + echo " Move the detail to docs/ai/.md, MyMistakes.md, decisions.md or git log." + return 1 + fi + printf " ✓ %-12s %3s/%s lines\n" "$rel" "$lines" "$cap" +} +budget_failed=0 +check_budget "AGENTS.md" 210 || budget_failed=1 +check_budget "ai.md" 100 || budget_failed=1 +check_budget "HANDOFF.md" 40 || budget_failed=1 +check_budget "TASKS.md" 120 || budget_failed=1 +[ "$budget_failed" -eq 0 ] || exit 1 + +echo "══ 2/4 CLEAN BUILD (expect 0 warnings) ══" +if [ -z "$BUILD_CMD" ]; then + echo "⚠ BUILD_CMD not configured — build step skipped." +else + [ -z "$CLEAN_CMD" ] || eval "$CLEAN_CMD" > /dev/null + OUT="$(eval "$BUILD_CMD" 2>&1)" + if echo "$OUT" | grep -qI "$WARN_PATTERN"; then + echo "✗ WARNINGS FOUND:" + echo "$OUT" | grep -i "$WARN_PATTERN" | sort -u + exit 1 + fi + echo "$OUT" | tail -3 + echo "✓ Build clean." +fi + +echo "══ 3/4 TEST SUITE ══" +if [ -z "$TEST_CMD" ]; then + echo "⚠ TEST_CMD not configured — test step skipped." +else + set +e + RUN="$(eval "$TEST_CMD" 2>&1)" + EXIT=$? + set -e + echo "$RUN" | tail -5 + if [ "$EXIT" -ne 0 ]; then + if [ -n "$KNOWN_FLAKY" ] && ! echo "$RUN" | grep -iE "fail" | grep -qvE "$KNOWN_FLAKY"; then + echo "⚠ Failures, but all match the known-flaky whitelist (OK)." + else + echo "✗ TEST FAILURES — investigate." + exit 1 + fi + fi +fi + +echo "══ 4/4 SCOPE CHECK ══" +"$ROOT/scripts/scope-check.sh" "$@" + +echo "" +echo "✓ All gates passed — safe to commit." diff --git a/templates/ai.md b/templates/ai.md new file mode 100644 index 0000000..5baf012 --- /dev/null +++ b/templates/ai.md @@ -0,0 +1,30 @@ +# (repo ``) — AI guide & router + +> Read [`AGENTS.md`](AGENTS.md) first: the rules and the invariants. This file is the **map** — +> what the product is, how it is built, and where the truth lives. No narrative, no status. + +## What it is + + + +## Build, run, test + + + +## Architecture + +| Path | Role | +|---|---| +| `/` | | + +## Where the truth lives + +| Subsystem | File | Read when | +|---|---|---| +| | [`docs/ai/.md`](docs/ai/.md) | | + +Lookup, not reading: [`MyMistakes.md`](MyMistakes.md) · [`TASKS.md`](TASKS.md) · `/index.md`. + +## Current state + +[`HANDOFF.md`](HANDOFF.md) — do not restate it here. diff --git a/templates/decisions.md b/templates/decisions.md new file mode 100644 index 0000000..4d5bd38 --- /dev/null +++ b/templates/decisions.md @@ -0,0 +1,12 @@ +# Decisions log — retired paths, kept so they are not re-litigated + +One dated line per decision that **no longer governs**, with the reason it died. Read only when +about to re-open one. + +## + +- **** — superseded by , because . + +## Out of scope — permanently + +- — . diff --git a/templates/docs-ai-index.md b/templates/docs-ai-index.md new file mode 100644 index 0000000..c0d6bdb --- /dev/null +++ b/templates/docs-ai-index.md @@ -0,0 +1,10 @@ +# docs/ai — index + +Subsystem truth, split out so a session pays only for what its task touches. `ai.md` routes here; +`AGENTS.md` carries the invariants that hold across every subsystem. + +| File | Covers | Read when | +|---|---|---| +| [`environment.md`](environment.md) | Hosts, ports, paths, build/run/test commands, test map | building, running, adding a test | +| [`decisions.md`](decisions.md) | Retired paths with cause of death; the permanent out-of-scope list | about to re-open a settled decision | +| .md | | | diff --git a/templates/environment.md b/templates/environment.md new file mode 100644 index 0000000..b4f35b6 --- /dev/null +++ b/templates/environment.md @@ -0,0 +1,34 @@ +# Environment — lookups + +Facts you grep for, never read start to finish. Add a line the first time one costs a hunt. + +## Hosts & access + +| Host | Address | Role | +|---|---|---| +| | | | + +SSH / credentials: . + +## Build, run, test + +```bash + + + + +``` + + + +## Paths + +- App data / config: `` +- Logs: `` (rotation: ) +- Build output / artifacts: `` + +## Test map + +| Area | Test file | Notes | +|---|---|---| +| | `` | | diff --git a/templates/handoff.md b/templates/handoff.md new file mode 100644 index 0000000..fef1b01 --- /dev/null +++ b/templates/handoff.md @@ -0,0 +1,18 @@ +# HANDOFF — () + +## State + +- Branch ``, worktree , **** (``). +- In flight: . + +## Next action + + + +## Landmines (live, not historical) + +- + +## Pending the user + +- diff --git a/templates/index.md b/templates/index.md new file mode 100644 index 0000000..eea38e3 --- /dev/null +++ b/templates/index.md @@ -0,0 +1,9 @@ +# — index + +One line on what this directory owns, then every file with its purpose. Details live in the files. + +| File | Purpose | +|---|---| +| `` | | + +Related: [`../other/index.md`](../other/index.md) diff --git a/templates/mymistakes.md b/templates/mymistakes.md new file mode 100644 index 0000000..34c9e7c --- /dev/null +++ b/templates/mymistakes.md @@ -0,0 +1,23 @@ +# MyMistakes — failure log + recipes + +## Recipes (grep here FIRST) + + + +### + +```bash + +``` + +Traps: . + +## Failure log (newest first) + +### — + +- **Symptom:** +- **Wrong guess:** +- **Actual cause:** +- **Rule now:** diff --git a/templates/schema.md b/templates/schema.md new file mode 100644 index 0000000..39a06cf --- /dev/null +++ b/templates/schema.md @@ -0,0 +1,35 @@ +# Memory map — conventions + +## Why files, not a database + +Grep-able, diffable, human-editable, portable; git gives versioning and history for free. Files +form a graph: each file is a node, each relative link an edge. + +## Inventory + +| File | Role | Entry point? | +|---|---|---| +| `AGENTS.md` | Rules + invariants | **always read** | +| `ai.md` | Router: product, build, architecture, where truth lives | yes | +| `HANDOFF.md` | Current state (≤40 lines, overwritten) | yes | +| `TASKS.md` | Active queue | when asking "what's next" | +| `docs/ai/*.md` | Subsystem truth, one file each | when the task touches it | +| `MyMistakes.md` | Failure log + recipes | grep first | + +## Rules + +1. **Semantic filenames.** No codes, no abbreviations. +2. **One `index.md` per code directory**, listing every file with a one-line purpose. +3. **Links over hierarchy.** Anything unreachable from `ai.md` may as well not exist. +4. **Stale facts get fixed, not appended.** +5. **Progressive disclosure.** Detail lives one level down, never crammed into the router. + +## Reading order + +1. `AGENTS.md` → 2. `HANDOFF.md` → 3. `ai.md` → 4. the one `docs/ai/.md` → 5. `/index.md` +→ 6. the source (always the authority over any memory file). + +## Integration rule + +Every change ships with the facts it **falsifies** corrected, in the same commit. Broader +restatement may be batched at a milestone. diff --git a/templates/tasks.md b/templates/tasks.md new file mode 100644 index 0000000..98dc1ab --- /dev/null +++ b/templates/tasks.md @@ -0,0 +1,22 @@ +# TASKS — the active queue + +> One line per live item; detail lives elsewhere. Done work goes to [`TASKS/archive.md`](TASKS/archive.md). +> Markers: ☐ queued · 🔶 in progress · ⏳ blocked · ⏸ deferred · ❌ retired. + +## Next up + +**** — + +## Queue + +| Task | Status | Scope | Detail | +|---|---|---|---| +| | ☐ | | | + +## Pending the user (not programming) + +- + +## Release gates (before the first shipped build) + +-